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
|
||||
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 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
|
||||
- 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! {
|
||||
fn #function_wrapper_ident<'a>(
|
||||
args: impl Into<pyo3::derive_utils::WrapPyFunctionArguments<'a>>
|
||||
) -> pyo3::PyResult<pyo3::PyObject> {
|
||||
) -> pyo3::PyResult<&'a pyo3::types::PyCFunction> {
|
||||
let arg = args.into();
|
||||
let (py, maybe_module) = arg.into_py_and_maybe_module();
|
||||
#wrapper
|
||||
|
@ -231,8 +231,7 @@ pub fn add_fn_to_module(
|
|||
};
|
||||
|
||||
let function = unsafe {
|
||||
pyo3::PyObject::from_owned_ptr(
|
||||
py,
|
||||
py.from_owned_ptr::<pyo3::types::PyCFunction>(
|
||||
pyo3::ffi::PyCFunction_NewEx(
|
||||
Box::into_raw(Box::new(_def.as_method_def())),
|
||||
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::floatobject::*;
|
||||
pub use self::frameobject::PyFrameObject;
|
||||
pub use self::funcobject::*;
|
||||
pub use self::genobject::*;
|
||||
pub use self::import::*;
|
||||
pub use self::intrcheck::*;
|
||||
|
@ -157,3 +158,5 @@ pub mod frameobject {
|
|||
|
||||
pub(crate) mod datetime;
|
||||
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::floatob::PyFloat;
|
||||
pub use self::function::{PyCFunction, PyFunction};
|
||||
pub use self::iterator::PyIterator;
|
||||
pub use self::list::PyList;
|
||||
pub use self::module::PyModule;
|
||||
|
@ -225,6 +226,7 @@ mod complex;
|
|||
mod datetime;
|
||||
mod dict;
|
||||
mod floatob;
|
||||
mod function;
|
||||
mod iterator;
|
||||
mod list;
|
||||
mod module;
|
||||
|
|
|
@ -9,8 +9,8 @@ use crate::ffi;
|
|||
use crate::instance::PyNativeType;
|
||||
use crate::pyclass::PyClass;
|
||||
use crate::type_object::PyTypeObject;
|
||||
use crate::types::PyTuple;
|
||||
use crate::types::{PyAny, PyDict, PyList};
|
||||
use crate::types::{PyCFunction, PyTuple};
|
||||
use crate::{AsPyPointer, IntoPy, Py, PyObject, Python};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::c_char;
|
||||
|
@ -275,12 +275,11 @@ impl PyModule {
|
|||
/// ```
|
||||
pub fn add_function<'a>(
|
||||
&'a self,
|
||||
wrapper: &impl Fn(&'a Self) -> PyResult<PyObject>,
|
||||
wrapper: &impl Fn(&'a Self) -> PyResult<&'a PyCFunction>,
|
||||
) -> PyResult<()> {
|
||||
let py = self.py();
|
||||
let function = wrapper(self)?;
|
||||
let name = function.getattr(py, "__name__")?;
|
||||
let name = name.extract(py)?;
|
||||
let name = function.getattr("__name__")?;
|
||||
let name = name.extract()?;
|
||||
self.add(name, function)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use pyo3::buffer::PyBuffer;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyCFunction, PyFunction};
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
||||
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