fix python exptension export
This commit is contained in:
parent
2fdbcd356a
commit
acc00b7738
14
README.md
14
README.md
|
@ -12,7 +12,7 @@ Python is licensed under the [Python License](https://docs.python.org/2/license.
|
|||
|
||||
Supported Python versions:
|
||||
|
||||
* Python 3.5 and up
|
||||
* Python2.7, Python 3.5 and up
|
||||
|
||||
Supported Rust version:
|
||||
|
||||
|
@ -74,15 +74,17 @@ features = ["extension-module"]
|
|||
**`src/lib.rs`**
|
||||
|
||||
```rust
|
||||
#[macro_use] extern crate pyo3;
|
||||
#![feature(proc_macro)]
|
||||
#![macro_use] extern crate pyo3;
|
||||
|
||||
use pyo3::{PyResult, Python};
|
||||
use pyo3::{py, PyResult, Python, PyModule};
|
||||
|
||||
// add bindings to the generated python module
|
||||
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
||||
py_module_init!(librust2py, PyInit__librust2py, |py, m| {
|
||||
try!(m.add(py, "__doc__", "This module is implemented in Rust."));
|
||||
try!(m.add(py, "sum_as_string", py_fn!(py, sum_as_string_py(a: i64, b:i64))));
|
||||
#[py::modinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add(py, "__doc__", "This module is implemented in Rust.")?;
|
||||
m.add(py, "sum_as_string", py_fn!(py, sum_as_string_py(a: i64, b:i64)))?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
|
|
|
@ -36,7 +36,12 @@ pub fn mod2init(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|||
// Build the output
|
||||
let init = module::build_py2_module_init(&mut ast, attr.to_string());
|
||||
|
||||
TokenStream::from_str(init.as_str()).unwrap()
|
||||
// Return the generated impl as a TokenStream
|
||||
let mut tokens = Tokens::new();
|
||||
ast.to_tokens(&mut tokens);
|
||||
let s = String::from(tokens.as_str()) + init.as_str();
|
||||
|
||||
TokenStream::from_str(s.as_str()).unwrap()
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
|
@ -50,7 +55,12 @@ pub fn mod3init(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|||
// Build the output
|
||||
let init = module::build_py3_module_init(&mut ast, attr.to_string());
|
||||
|
||||
TokenStream::from_str(init.as_str()).unwrap()
|
||||
// Return the generated impl as a TokenStream
|
||||
let mut tokens = Tokens::new();
|
||||
ast.to_tokens(&mut tokens);
|
||||
let s = String::from(tokens.as_str()) + init.as_str();
|
||||
|
||||
TokenStream::from_str(s.as_str()).unwrap()
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
|
|
|
@ -6,47 +6,35 @@ use quote::Tokens;
|
|||
|
||||
pub fn build_py3_module_init(ast: &mut syn::Item, attr: String) -> Tokens {
|
||||
let modname = &attr.to_string()[1..attr.to_string().len()-1].to_string();
|
||||
let name = syn::Ident::from(modname.as_ref());
|
||||
|
||||
println!("MOD: {:?}", modname);
|
||||
|
||||
let tokens = match ast.node {
|
||||
match ast.node {
|
||||
syn::ItemKind::Fn(_, _, _, _, _, _) => {
|
||||
py3_init(&ast.ident, &name);
|
||||
py3_init(&ast.ident, &modname)
|
||||
},
|
||||
_ => panic!("#[modinit] can only be used with fn block"),
|
||||
};
|
||||
|
||||
let dummy_const = syn::Ident::new(format!("_IMPL_PYO3_MODINIT_{}", modname.trim()));
|
||||
|
||||
quote! {
|
||||
#[feature(specialization)]
|
||||
#[allow(non_upper_case_globals, unused_attributes,
|
||||
unused_qualifications, unused_variables, non_camel_case_types)]
|
||||
const #dummy_const: () = {
|
||||
extern crate pyo3 as _pyo3;
|
||||
|
||||
#tokens
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn py3_init(fnname: &syn::Ident, name: &syn::Ident) -> Tokens {
|
||||
pub fn py3_init(fnname: &syn::Ident, name: &String) -> Tokens {
|
||||
let cb_name = syn::Ident::from(format!("PyInit_{}", name.trim()).as_ref());
|
||||
quote! {
|
||||
#[no_mangle]
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe extern "C" fn PyInit_#name() -> *mut _pyo3::ffi::PyObject {
|
||||
static mut MODULE_DEF: $crate::ffi::PyModuleDef = $crate::ffi::PyModuleDef_INIT;
|
||||
pub unsafe extern "C" fn #cb_name() -> *mut ::pyo3::ffi::PyObject {
|
||||
use std;
|
||||
extern crate pyo3 as _pyo3;
|
||||
|
||||
static mut MODULE_DEF: _pyo3::ffi::PyModuleDef = _pyo3::ffi::PyModuleDef_INIT;
|
||||
// We can't convert &'static str to *const c_char within a static initializer,
|
||||
// so we'll do it here in the module initialization:
|
||||
MODULE_DEF.m_name = concat!(stringify!($name), "\0").as_ptr() as *const _;
|
||||
MODULE_DEF.m_name = concat!(stringify!(#cb_name), "\0").as_ptr() as *const _;
|
||||
|
||||
let guard = _pyo3::callback::AbortOnDrop("py_module_init");
|
||||
let py = _pyo3::Python::assume_gil_acquired();
|
||||
_pyo3::ffi::PyEval_InitThreads();
|
||||
let module = _pyo3::ffi::PyModule_Create(def);
|
||||
let module = _pyo3::ffi::PyModule_Create(&mut MODULE_DEF);
|
||||
if module.is_null() {
|
||||
mem::forget(guard);
|
||||
std::mem::forget(guard);
|
||||
return module;
|
||||
}
|
||||
|
||||
|
@ -56,18 +44,18 @@ pub fn py3_init(fnname: &syn::Ident, name: &syn::Ident) -> Tokens {
|
|||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
_pyo3::PyErr::from(e).restore(py);
|
||||
mem::forget(guard);
|
||||
std::mem::forget(guard);
|
||||
return ptr::null_mut();
|
||||
}
|
||||
};
|
||||
let ret = match #fnname(py, &module) {
|
||||
Ok(()) => module.into_ptr(),
|
||||
Ok(_) => module.into_ptr(),
|
||||
Err(e) => {
|
||||
e.restore(py);
|
||||
ptr::null_mut()
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
};
|
||||
mem::forget(guard);
|
||||
std::mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
@ -75,59 +63,50 @@ pub fn py3_init(fnname: &syn::Ident, name: &syn::Ident) -> Tokens {
|
|||
|
||||
pub fn build_py2_module_init(ast: &mut syn::Item, attr: String) -> Tokens {
|
||||
let modname = &attr.to_string()[1..attr.to_string().len()-1].to_string();
|
||||
let name = syn::Ident::from(modname.as_ref());
|
||||
|
||||
let tokens = match ast.node {
|
||||
match ast.node {
|
||||
syn::ItemKind::Fn(_, _, _, _, _, _) => {
|
||||
py2_init(&ast.ident, &name);
|
||||
py2_init(&ast.ident, &modname)
|
||||
},
|
||||
_ => panic!("#[modinit] can only be used with fn block"),
|
||||
};
|
||||
|
||||
let dummy_const = syn::Ident::new(format!("_IMPL_PYO3_MODINIT_{}", modname.trim()));
|
||||
|
||||
quote! {
|
||||
#[feature(specialization)]
|
||||
#[allow(non_upper_case_globals, unused_attributes,
|
||||
unused_qualifications, unused_variables, non_camel_case_types)]
|
||||
const #dummy_const: () = {
|
||||
extern crate pyo3 as _pyo3;
|
||||
|
||||
#tokens
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn py2_init(fnname: &syn::Ident, name: &syn::Ident) -> Tokens {
|
||||
pub fn py2_init(fnname: &syn::Ident, name: &String) -> Tokens {
|
||||
let cb_name = syn::Ident::from(format!("init{}", name.trim()).as_ref());
|
||||
|
||||
quote! {
|
||||
#[no_mangle]
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe extern "C" fn init#name() -> *mut _pyo3::ffi::PyObject {
|
||||
use pyo3::ffi;
|
||||
pub unsafe extern "C" fn #cb_name() {
|
||||
extern crate pyo3 as _pyo3;
|
||||
use std;
|
||||
|
||||
let name = concat!(stringify!($name), "\0").as_ptr() as *const _;
|
||||
let guard = function::AbortOnDrop("py_module_initializer");
|
||||
let py = Python::assume_gil_acquired();
|
||||
ffi::PyEval_InitThreads();
|
||||
let module = ffi::Py_InitModule(name, ptr::null_mut());
|
||||
let name = concat!(stringify!(#cb_name), "\0").as_ptr() as *const _;
|
||||
let guard = _pyo3::callback::AbortOnDrop("py_module_initializer");
|
||||
let py = pyo3::Python::assume_gil_acquired();
|
||||
pyo3::ffi::PyEval_InitThreads();
|
||||
let module = pyo3::ffi::Py_InitModule(name, std::ptr::null_mut());
|
||||
if module.is_null() {
|
||||
mem::forget(guard);
|
||||
return;
|
||||
std::mem::forget(guard);
|
||||
return
|
||||
}
|
||||
|
||||
let module = match PyObject::from_borrowed_ptr(py, module).cast_into::<PyModule>(py) {
|
||||
let module = match pyo3::PyObject::from_borrowed_ptr(
|
||||
py, module).cast_into::<pyo3::PyModule>(py)
|
||||
{
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
_pyo3::PyErr::from(e).restore(py);
|
||||
mem::forget(guard);
|
||||
return;
|
||||
std::mem::forget(guard);
|
||||
return
|
||||
}
|
||||
};
|
||||
let ret = match #fnname(py, &module) {
|
||||
Ok(()) => (),
|
||||
Err(e) => e.restore(py)
|
||||
};
|
||||
mem::forget(guard);
|
||||
std::mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue