[−][src]Macro cpython::py_capsule_fn
Macro to retrieve a function pointer capsule.
This is not suitable for architectures where the sizes of function and data pointers
differ.
For general explanations about capsules, see PyCapsule
.
Usage
py_capsule_fn!(from some.python.module import capsulename as rustmodule signature (args) -> ret_type)
Similarly to py_capsule!, the macro defines
- a Rust module according to the name provided by the caller (here,
rustmodule
) - a type alias for the given signature
- a retrieval function:
mod $rustmod { pub type CapsuleFn = unsafe extern "C" (args) -> ret_type ; pub unsafe fn retrieve<'a>(py: Python) -> PyResult<CapsuleFn) { ... } }
- a
RawPyObject
type suitable for signatures that involve Python C objects; it can be used incpython
public API involving raw FFI pointers, such asfrom_owned_ptr
.
The first call to retrieve()
is cached for subsequent calls.
Examples
Full example with primitive types
There is in the Python library no capsule enclosing a function pointer directly,
although the documentation presents it as a valid use-case. For this example, we'll
therefore have to create one, using the PyCapsule
constructor, and to set it in an
existing module (not to imply that a real extension should follow that example
and set capsules in modules they don't define!)
#[macro_use] extern crate cpython; extern crate libc; use cpython::{PyCapsule, Python, FromPyObject}; use libc::{c_int, c_void}; extern "C" fn inc(a: c_int) -> c_int { a + 1 } /// for testing purposes, stores a capsule named `sys.capsfn`` pointing to `inc()`. fn create_capsule() { let gil = Python::acquire_gil(); let py = gil.python(); let pymod = py.import("sys").unwrap(); let caps = PyCapsule::new(py, inc as *const c_void, "sys.capsfn").unwrap(); pymod.add(py, "capsfn", caps).unwrap(); } py_capsule_fn!(from sys import capsfn as capsmod signature (a: c_int) -> c_int); // One could, e.g., reexport if needed: pub use capsmod::CapsuleFn; fn retrieve_use_capsule() { let gil = Python::acquire_gil(); let py = gil.python(); let fun = capsmod::retrieve(py).unwrap(); assert_eq!( unsafe { fun(1) }, 2); // let's demonstrate the (reexported) function type let g: CapsuleFn = fun; } fn main() { create_capsule(); retrieve_use_capsule(); // second call uses the cached function pointer retrieve_use_capsule(); }
With Python objects
In this example, we lend a Python object and receive a new one of which we take ownership.
#[macro_use] extern crate cpython; use cpython::{PyCapsule, PyObject, PyResult, Python}; py_capsule_fn!(from some.mod import capsfn as capsmod signature (raw: *mut RawPyObject) -> *mut RawPyObject); fn retrieve_use_capsule(py: Python, obj: PyObject) -> PyResult<PyObject> { let fun = capsmod::retrieve(py)?; let raw = obj.as_ptr(); Ok(unsafe { PyObject::from_owned_ptr(py, fun(raw)) }) }