py_module_initializer! for python 3
This commit is contained in:
parent
db47455904
commit
8c8779e3fb
|
@ -4,8 +4,8 @@ env:
|
||||||
global:
|
global:
|
||||||
- secure: g4kCg8twONwKPquuJmYrvGjo2n0lNtWTbyzFOITNn8FgCxNK2j38Qc9/UhErTR3g3rDjVzsTHZ8FTH7TJZrOK1Nzz90tJG6JHqUv77ufkcBlxgwwjilOz84uQhkDTMpLitMEeQDLEynKeWbxrjtc5LIpjEkxOPk5eiqwzKRN14c=
|
- secure: g4kCg8twONwKPquuJmYrvGjo2n0lNtWTbyzFOITNn8FgCxNK2j38Qc9/UhErTR3g3rDjVzsTHZ8FTH7TJZrOK1Nzz90tJG6JHqUv77ufkcBlxgwwjilOz84uQhkDTMpLitMEeQDLEynKeWbxrjtc5LIpjEkxOPk5eiqwzKRN14c=
|
||||||
script:
|
script:
|
||||||
- cargo build --verbose
|
- make test extensions PY=2
|
||||||
- cargo test --verbose
|
- make test extensions PY=3
|
||||||
# 'cargo doc' is broken due to https://github.com/rust-lang/cargo/issues/1622
|
# 'cargo doc' is broken due to https://github.com/rust-lang/cargo/issues/1622
|
||||||
# - cargo doc --verbose
|
# - cargo doc --verbose
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,9 @@ exclude = [
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc="*"
|
libc = "*"
|
||||||
num="*"
|
num = "*"
|
||||||
|
interpolate_idents = "*"
|
||||||
|
|
||||||
# These features are both optional, but you must pick one to
|
# These features are both optional, but you must pick one to
|
||||||
# indicate which python ffi you are trying to bind to.
|
# indicate which python ffi you are trying to bind to.
|
||||||
|
|
19
Makefile
19
Makefile
|
@ -1,18 +1,29 @@
|
||||||
.PHONY: default build test doc extensions clean
|
.PHONY: default build test doc extensions clean
|
||||||
|
|
||||||
|
ifndef PY
|
||||||
|
PY=3
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(PY),2)
|
||||||
|
FEATURES=--features python27-sys --no-default-features
|
||||||
|
endif
|
||||||
|
ifeq ($(PY),3)
|
||||||
|
FEATURES=--features python3-sys --no-default-features
|
||||||
|
endif
|
||||||
|
|
||||||
default: test extensions
|
default: test extensions
|
||||||
|
|
||||||
build:
|
build:
|
||||||
cargo build
|
cargo build $(FEATURES)
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
cargo test
|
cargo test $(FEATURES)
|
||||||
|
|
||||||
doc: build
|
doc: build
|
||||||
cargo doc --no-deps
|
cargo doc --no-deps $(FEATURES)
|
||||||
|
|
||||||
extensions: build
|
extensions: build
|
||||||
make -C extensions/
|
make -C extensions/ PY=$(PY)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -r target
|
rm -r target
|
||||||
|
|
|
@ -3,6 +3,10 @@ rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
|
ifndef PY
|
||||||
|
PY=3
|
||||||
|
endif
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@ -13,15 +17,16 @@ clean:
|
||||||
stamps:
|
stamps:
|
||||||
mkdir stamps
|
mkdir stamps
|
||||||
|
|
||||||
stamps/rust-cpython: $(call rwildcard,../src,*.rs) Makefile | stamps
|
stamps/rust-cpython-$(PY): $(call rwildcard,../src,*.rs) Makefile | stamps
|
||||||
cd .. && cargo build
|
-rm stamps/rust-cpython-*
|
||||||
|
cd .. && make build PY=$(PY)
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
%.so: %.rs stamps/rust-cpython
|
%.so: %.rs stamps/rust-cpython-$(PY)
|
||||||
rustc $< -L $(TARGETDIR) -L $(TARGETDIR)/deps -o $@
|
rustc $< -L $(TARGETDIR) -L $(TARGETDIR)/deps -o $@
|
||||||
|
|
||||||
hello.out: hello.so
|
hello.out: hello.so
|
||||||
python -c "import hello; hello.run(hello.val())" 2>&1 | tee $@
|
python$(PY) -c "import hello; hello.run(hello.val())" 2>&1 | tee $@
|
||||||
|
|
||||||
all: stamps/test-hello
|
all: stamps/test-hello
|
||||||
stamps/test-hello: hello.out
|
stamps/test-hello: hello.out
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#![crate_type = "dylib"]
|
#![crate_type = "dylib"]
|
||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(interpolate_idents)]
|
||||||
|
|
||||||
#[macro_use] extern crate cpython;
|
#[macro_use] extern crate cpython;
|
||||||
|
|
||||||
use cpython::{PyObject, PyResult, PyModule, Python, PyTuple};
|
use cpython::{PyObject, PyResult, PyModule, Python, PyTuple};
|
||||||
|
|
||||||
py_module_initializer!("hello", inithello, |py, m| {
|
py_module_initializer!(hello, |py, m| {
|
||||||
try!(m.add("__doc__", "Module documentation string"));
|
try!(m.add("__doc__", "Module documentation string"));
|
||||||
try!(m.add("run", py_func!(py, run)));
|
try!(m.add("run", py_func!(py, run)));
|
||||||
try!(add_val(py, &m));
|
try!(add_val(py, &m));
|
||||||
|
|
|
@ -40,11 +40,13 @@ pub struct PyModuleDef_Base {
|
||||||
impl ::std::clone::Clone for PyModuleDef_Base {
|
impl ::std::clone::Clone for PyModuleDef_Base {
|
||||||
fn clone(&self) -> PyModuleDef_Base { *self }
|
fn clone(&self) -> PyModuleDef_Base { *self }
|
||||||
}
|
}
|
||||||
impl ::std::default::Default for PyModuleDef_Base {
|
|
||||||
fn default() -> PyModuleDef_Base {
|
pub const PyModuleDef_HEAD_INIT: PyModuleDef_Base = PyModuleDef_Base {
|
||||||
unsafe { ::std::mem::zeroed() }
|
ob_base: PyObject_HEAD_INIT,
|
||||||
}
|
m_init: None,
|
||||||
}
|
m_index: 0,
|
||||||
|
m_copy: 0 as *mut PyObject
|
||||||
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
|
@ -62,7 +64,5 @@ pub struct PyModuleDef {
|
||||||
impl ::std::clone::Clone for PyModuleDef {
|
impl ::std::clone::Clone for PyModuleDef {
|
||||||
fn clone(&self) -> PyModuleDef { *self }
|
fn clone(&self) -> PyModuleDef { *self }
|
||||||
}
|
}
|
||||||
impl ::std::default::Default for PyModuleDef {
|
|
||||||
fn default() -> PyModuleDef { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,20 @@ pub struct PyObject {
|
||||||
pub ob_type: *mut PyTypeObject,
|
pub ob_type: *mut PyTypeObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(py_sys_config="Py_TRACE_REFS")]
|
||||||
|
pub const PyObject_HEAD_INIT: PyObject = PyObject {
|
||||||
|
_ob_next: 0 as *mut PyObject,
|
||||||
|
_ob_prev: 0 as *mut PyObject,
|
||||||
|
ob_refcnt: 1,
|
||||||
|
ob_type: 0 as *mut PyTypeObject
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(py_sys_config="Py_TRACE_REFS"))]
|
||||||
|
pub const PyObject_HEAD_INIT: PyObject = PyObject {
|
||||||
|
ob_refcnt: 1,
|
||||||
|
ob_type: 0 as *mut PyTypeObject
|
||||||
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct PyVarObject {
|
pub struct PyVarObject {
|
||||||
|
|
53
src/lib.rs
53
src/lib.rs
|
@ -22,6 +22,8 @@
|
||||||
#![feature(optin_builtin_traits)] // for opting out of Sync/Send
|
#![feature(optin_builtin_traits)] // for opting out of Sync/Send
|
||||||
#![feature(slice_patterns)] // for tuple_conversion macros
|
#![feature(slice_patterns)] // for tuple_conversion macros
|
||||||
#![feature(utf8_error)] // for translating Utf8Error to python exception
|
#![feature(utf8_error)] // for translating Utf8Error to python exception
|
||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(interpolate_idents)]
|
||||||
#![allow(unused_imports, unused_variables)]
|
#![allow(unused_imports, unused_variables)]
|
||||||
|
|
||||||
//! Rust bindings to the python interpreter.
|
//! Rust bindings to the python interpreter.
|
||||||
|
@ -129,10 +131,12 @@ pub mod _detail {
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// #![crate_type = "dylib"]
|
/// #![crate_type = "dylib"]
|
||||||
|
/// #![feature(plugin)]
|
||||||
|
/// #![plugin(interpolate_idents)]
|
||||||
/// #[macro_use] extern crate cpython;
|
/// #[macro_use] extern crate cpython;
|
||||||
/// use cpython::{Python, PyResult, PyObject, PyTuple};
|
/// use cpython::{Python, PyResult, PyObject, PyTuple};
|
||||||
///
|
///
|
||||||
/// py_module_initializer!("example", initexample, |py, m| {
|
/// py_module_initializer!(example, |py, m| {
|
||||||
/// try!(m.add("__doc__", "Module documentation string"));
|
/// try!(m.add("__doc__", "Module documentation string"));
|
||||||
/// try!(m.add("run", py_func!(py, run)));
|
/// try!(m.add("run", py_func!(py, run)));
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
|
@ -158,18 +162,55 @@ pub mod _detail {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg(feature="python27-sys")]
|
||||||
macro_rules! py_module_initializer {
|
macro_rules! py_module_initializer {
|
||||||
($name: tt, $init_funcname: ident, $init: expr) => {
|
($name: ident, $init: expr) => ( interpolate_idents! {
|
||||||
#[no_mangle]
|
#[[no_mangle]]
|
||||||
pub extern "C" fn $init_funcname() {
|
#[allow(non_snake_case)]
|
||||||
|
pub extern "C" fn [ init $name ]() {
|
||||||
let py = unsafe { $crate::Python::assume_gil_acquired() };
|
let py = unsafe { $crate::Python::assume_gil_acquired() };
|
||||||
let name = unsafe { ::std::ffi::CStr::from_ptr(concat!($name, "\0").as_ptr() as *const _) };
|
let name = unsafe { ::std::ffi::CStr::from_ptr(concat!(stringify!($name), "\0").as_ptr() as *const _) };
|
||||||
match $crate::PyModule::_init(py, name, $init) {
|
match $crate::PyModule::_init(py, name, $init) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(e) => e.restore()
|
Err(e) => e.restore()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[cfg(feature="python3-sys")]
|
||||||
|
macro_rules! py_module_initializer {
|
||||||
|
($name: ident, $init: expr) => ( interpolate_idents! {
|
||||||
|
#[[no_mangle]]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub extern "C" fn [ PyInit_ $name ]() -> *mut $crate::_detail::ffi::PyObject {
|
||||||
|
let py = unsafe { $crate::Python::assume_gil_acquired() };
|
||||||
|
static mut module_def: $crate::_detail::ffi::PyModuleDef = $crate::_detail::ffi::PyModuleDef {
|
||||||
|
m_base: $crate::_detail::ffi::PyModuleDef_HEAD_INIT,
|
||||||
|
m_name: 0 as *const _,
|
||||||
|
m_doc: 0 as *const _,
|
||||||
|
m_size: 0, // we don't use per-module state
|
||||||
|
m_methods: 0 as *mut _,
|
||||||
|
m_reload: None,
|
||||||
|
m_traverse: None,
|
||||||
|
m_clear: None,
|
||||||
|
m_free: None
|
||||||
|
};
|
||||||
|
// We can't convert &'static str to *const c_char within a static initializer,
|
||||||
|
// so we'll do it here in the module initialization:
|
||||||
|
unsafe {
|
||||||
|
module_def.m_name = concat!(stringify!($name), "\0").as_ptr() as *const _;
|
||||||
|
}
|
||||||
|
match $crate::PyModule::_init(py, unsafe { &mut module_def }, $init) {
|
||||||
|
Ok(m) => $crate::ToPythonPointer::steal_ptr(m),
|
||||||
|
Err(e) => {
|
||||||
|
e.restore();
|
||||||
|
return ::std::ptr::null_mut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a python callable object that invokes a Rust function.
|
/// Creates a python callable object that invokes a Rust function.
|
||||||
|
|
|
@ -47,13 +47,24 @@ impl <'p> PyModule<'p> {
|
||||||
// Helper method for module_initializer!() macro, do not use directly!
|
// Helper method for module_initializer!() macro, do not use directly!
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(feature="python27-sys")]
|
#[cfg(feature="python27-sys")]
|
||||||
pub fn _init<F, R>(py: Python<'p>, name: &CStr, init: F) -> PyResult<'p, R>
|
pub fn _init<F>(py: Python<'p>, name: &CStr, init: F) -> PyResult<'p, ()>
|
||||||
where F: FnOnce(Python<'p>, PyModule<'p>) -> PyResult<'p, R> {
|
where F: FnOnce(Python<'p>, &PyModule<'p>) -> PyResult<'p, ()> {
|
||||||
let module = try!(unsafe {
|
let module = try!(unsafe {
|
||||||
err::result_from_borrowed_ptr(py, ffi::Py_InitModule(name.as_ptr(), std::ptr::null_mut()))
|
err::result_from_borrowed_ptr(py, ffi::Py_InitModule(name.as_ptr(), std::ptr::null_mut()))
|
||||||
});
|
});
|
||||||
let module = try!(module.cast_into::<PyModule>());
|
let module = try!(module.cast_into::<PyModule>());
|
||||||
init(py, module)
|
init(py, &module)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg(feature="python3-sys")]
|
||||||
|
pub fn _init<F>(py: Python<'p>, def: *mut ffi::PyModuleDef, init: F) -> PyResult<'p, PyModule<'p>>
|
||||||
|
where F: FnOnce(Python<'p>, &PyModule<'p>) -> PyResult<'p, ()> {
|
||||||
|
let module: PyModule = try!(unsafe {
|
||||||
|
err::result_cast_from_owned_ptr(py, ffi::PyModule_Create(def))
|
||||||
|
});
|
||||||
|
try!(init(py, &module));
|
||||||
|
Ok(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the dictionary object that implements module‘s namespace;
|
/// Return the dictionary object that implements module‘s namespace;
|
||||||
|
|
Loading…
Reference in New Issue