Add native Function native types.
Add bindings for PyCFunction, PyFunction, PyClassMethod and PyStaticMethod.
This commit is contained in:
parent
64b06ea9ec
commit
2e8010b5df
|
@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Add macro attribute to `#[pyfn]` and `#[pyfunction]` to pass the module of a Python function to the function
|
- Add macro attribute to `#[pyfn]` and `#[pyfunction]` to pass the module of a Python function to the function
|
||||||
body. [#1143](https://github.com/PyO3/pyo3/pull/1143)
|
body. [#1143](https://github.com/PyO3/pyo3/pull/1143)
|
||||||
- Add `add_function()` and `add_submodule()` functions to `PyModule` [#1143](https://github.com/PyO3/pyo3/pull/1143)
|
- Add `add_function()` and `add_submodule()` functions to `PyModule` [#1143](https://github.com/PyO3/pyo3/pull/1143)
|
||||||
|
- Add native `PyCFunction` and `PyFunction` types, change `add_function` to take a wrapper returning
|
||||||
|
a `&PyCFunction`instead of `PyObject`. [#1163](https://github.com/PyO3/pyo3/pull/1163)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Exception types have been renamed from e.g. `RuntimeError` to `PyRuntimeError`, and are now only accessible by `&T` or `Py<T>` similar to other Python-native types. The old names continue to exist but are deprecated. [#1024](https://github.com/PyO3/pyo3/pull/1024)
|
- Exception types have been renamed from e.g. `RuntimeError` to `PyRuntimeError`, and are now only accessible by `&T` or `Py<T>` similar to other Python-native types. The old names continue to exist but are deprecated. [#1024](https://github.com/PyO3/pyo3/pull/1024)
|
||||||
|
|
|
@ -209,7 +209,7 @@ pub fn add_fn_to_module(
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
fn #function_wrapper_ident<'a>(
|
fn #function_wrapper_ident<'a>(
|
||||||
args: impl Into<pyo3::derive_utils::WrapPyFunctionArguments<'a>>
|
args: impl Into<pyo3::derive_utils::WrapPyFunctionArguments<'a>>
|
||||||
) -> pyo3::PyResult<pyo3::PyObject> {
|
) -> pyo3::PyResult<&'a pyo3::types::PyCFunction> {
|
||||||
let arg = args.into();
|
let arg = args.into();
|
||||||
let (py, maybe_module) = arg.into_py_and_maybe_module();
|
let (py, maybe_module) = arg.into_py_and_maybe_module();
|
||||||
#wrapper
|
#wrapper
|
||||||
|
@ -231,8 +231,7 @@ pub fn add_fn_to_module(
|
||||||
};
|
};
|
||||||
|
|
||||||
let function = unsafe {
|
let function = unsafe {
|
||||||
pyo3::PyObject::from_owned_ptr(
|
py.from_owned_ptr::<pyo3::types::PyCFunction>(
|
||||||
py,
|
|
||||||
pyo3::ffi::PyCFunction_NewEx(
|
pyo3::ffi::PyCFunction_NewEx(
|
||||||
Box::into_raw(Box::new(_def.as_method_def())),
|
Box::into_raw(Box::new(_def.as_method_def())),
|
||||||
mod_ptr,
|
mod_ptr,
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
use std::os::raw::c_int;
|
||||||
|
|
||||||
|
use crate::ffi::object::{PyObject, PyTypeObject, Py_TYPE};
|
||||||
|
|
||||||
|
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||||
|
extern "C" {
|
||||||
|
#[cfg_attr(PyPy, link_name = "PyPyFunction_Type")]
|
||||||
|
pub static mut PyFunction_Type: PyTypeObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn PyFunction_Check(op: *mut PyObject) -> c_int {
|
||||||
|
(Py_TYPE(op) == &mut PyFunction_Type) as c_int
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn PyFunction_NewWithQualName(
|
||||||
|
code: *mut PyObject,
|
||||||
|
globals: *mut PyObject,
|
||||||
|
qualname: *mut PyObject,
|
||||||
|
) -> *mut PyObject;
|
||||||
|
pub fn PyFunction_New(code: *mut PyObject, globals: *mut PyObject) -> *mut PyObject;
|
||||||
|
pub fn PyFunction_Code(op: *mut PyObject) -> *mut PyObject;
|
||||||
|
pub fn PyFunction_GetGlobals(op: *mut PyObject) -> *mut PyObject;
|
||||||
|
pub fn PyFunction_GetModule(op: *mut PyObject) -> *mut PyObject;
|
||||||
|
pub fn PyFunction_GetDefaults(op: *mut PyObject) -> *mut PyObject;
|
||||||
|
pub fn PyFunction_SetDefaults(op: *mut PyObject, defaults: *mut PyObject) -> c_int;
|
||||||
|
pub fn PyFunction_GetKwDefaults(op: *mut PyObject) -> *mut PyObject;
|
||||||
|
pub fn PyFunction_SetKwDefaults(op: *mut PyObject, defaults: *mut PyObject) -> c_int;
|
||||||
|
pub fn PyFunction_GetClosure(op: *mut PyObject) -> *mut PyObject;
|
||||||
|
pub fn PyFunction_SetClosure(op: *mut PyObject, closure: *mut PyObject) -> c_int;
|
||||||
|
pub fn PyFunction_GetAnnotations(op: *mut PyObject) -> *mut PyObject;
|
||||||
|
pub fn PyFunction_SetAnnotations(op: *mut PyObject, annotations: *mut PyObject) -> c_int;
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ pub use self::eval::*;
|
||||||
pub use self::fileobject::*;
|
pub use self::fileobject::*;
|
||||||
pub use self::floatobject::*;
|
pub use self::floatobject::*;
|
||||||
pub use self::frameobject::PyFrameObject;
|
pub use self::frameobject::PyFrameObject;
|
||||||
|
pub use self::funcobject::*;
|
||||||
pub use self::genobject::*;
|
pub use self::genobject::*;
|
||||||
pub use self::import::*;
|
pub use self::import::*;
|
||||||
pub use self::intrcheck::*;
|
pub use self::intrcheck::*;
|
||||||
|
@ -157,3 +158,5 @@ pub mod frameobject {
|
||||||
|
|
||||||
pub(crate) mod datetime;
|
pub(crate) mod datetime;
|
||||||
pub(crate) mod marshal;
|
pub(crate) mod marshal;
|
||||||
|
|
||||||
|
pub(crate) mod funcobject;
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
use crate::ffi;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Represents a builtin Python function object.
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct PyCFunction(PyAny);
|
||||||
|
|
||||||
|
pyobject_native_var_type!(PyCFunction, ffi::PyCFunction_Type, ffi::PyCFunction_Check);
|
||||||
|
|
||||||
|
/// Represents a Python function object.
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct PyFunction(PyAny);
|
||||||
|
|
||||||
|
pyobject_native_var_type!(PyFunction, ffi::PyFunction_Type, ffi::PyFunction_Check);
|
|
@ -13,6 +13,7 @@ pub use self::datetime::{
|
||||||
};
|
};
|
||||||
pub use self::dict::{IntoPyDict, PyDict};
|
pub use self::dict::{IntoPyDict, PyDict};
|
||||||
pub use self::floatob::PyFloat;
|
pub use self::floatob::PyFloat;
|
||||||
|
pub use self::function::{PyCFunction, PyFunction};
|
||||||
pub use self::iterator::PyIterator;
|
pub use self::iterator::PyIterator;
|
||||||
pub use self::list::PyList;
|
pub use self::list::PyList;
|
||||||
pub use self::module::PyModule;
|
pub use self::module::PyModule;
|
||||||
|
@ -225,6 +226,7 @@ mod complex;
|
||||||
mod datetime;
|
mod datetime;
|
||||||
mod dict;
|
mod dict;
|
||||||
mod floatob;
|
mod floatob;
|
||||||
|
mod function;
|
||||||
mod iterator;
|
mod iterator;
|
||||||
mod list;
|
mod list;
|
||||||
mod module;
|
mod module;
|
||||||
|
|
|
@ -9,8 +9,8 @@ use crate::ffi;
|
||||||
use crate::instance::PyNativeType;
|
use crate::instance::PyNativeType;
|
||||||
use crate::pyclass::PyClass;
|
use crate::pyclass::PyClass;
|
||||||
use crate::type_object::PyTypeObject;
|
use crate::type_object::PyTypeObject;
|
||||||
use crate::types::PyTuple;
|
|
||||||
use crate::types::{PyAny, PyDict, PyList};
|
use crate::types::{PyAny, PyDict, PyList};
|
||||||
|
use crate::types::{PyCFunction, PyTuple};
|
||||||
use crate::{AsPyPointer, IntoPy, Py, PyObject, Python};
|
use crate::{AsPyPointer, IntoPy, Py, PyObject, Python};
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
@ -275,12 +275,11 @@ impl PyModule {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn add_function<'a>(
|
pub fn add_function<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
wrapper: &impl Fn(&'a Self) -> PyResult<PyObject>,
|
wrapper: &impl Fn(&'a Self) -> PyResult<&'a PyCFunction>,
|
||||||
) -> PyResult<()> {
|
) -> PyResult<()> {
|
||||||
let py = self.py();
|
|
||||||
let function = wrapper(self)?;
|
let function = wrapper(self)?;
|
||||||
let name = function.getattr(py, "__name__")?;
|
let name = function.getattr("__name__")?;
|
||||||
let name = name.extract(py)?;
|
let name = name.extract()?;
|
||||||
self.add(name, function)
|
self.add(name, function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use pyo3::buffer::PyBuffer;
|
use pyo3::buffer::PyBuffer;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
use pyo3::types::{PyCFunction, PyFunction};
|
||||||
use pyo3::wrap_pyfunction;
|
use pyo3::wrap_pyfunction;
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
@ -62,3 +63,34 @@ assert a, array.array("i", [2, 4, 6, 8])
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn function_with_pyfunction_arg(fun: &PyFunction) -> PyResult<&PyAny> {
|
||||||
|
fun.call((), None)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn function_with_pycfunction_arg(fun: &PyCFunction) -> PyResult<&PyAny> {
|
||||||
|
fun.call((), None)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_functions_with_function_args() {
|
||||||
|
let gil = Python::acquire_gil();
|
||||||
|
let py = gil.python();
|
||||||
|
let py_func_arg = wrap_pyfunction!(function_with_pyfunction_arg)(py).unwrap();
|
||||||
|
let py_cfunc_arg = wrap_pyfunction!(function_with_pycfunction_arg)(py).unwrap();
|
||||||
|
let bool_to_string = wrap_pyfunction!(optional_bool)(py).unwrap();
|
||||||
|
|
||||||
|
pyo3::py_run!(
|
||||||
|
py,
|
||||||
|
py_func_arg
|
||||||
|
py_cfunc_arg
|
||||||
|
bool_to_string,
|
||||||
|
r#"
|
||||||
|
def foo(): return "bar"
|
||||||
|
assert py_func_arg(foo) == "bar"
|
||||||
|
assert py_cfunc_arg(bool_to_string) == "Some(true)"
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue