Macro cpython::py_fn

source ·
macro_rules! py_fn {
    ($py:expr, $f:ident $plist:tt ) => { ... };
    ($py:ident, $f:ident $plist:tt -> $ret:ty { $($body:tt)* } ) => { ... };
}
Expand description

Creates a Python callable object that invokes a Rust function.

There are two forms of this macro:

  1. py_fn!(py, f(parameter_list))
  2. py_fn!(py, f(parameter_list) -> PyResult<T> { body })

both forms return a value of type PyObject. This python object is a callable object that invokes the Rust function when called.

When called, the arguments are converted into the Rust types specified in the parameter list. See py_argparse!() for details on argument parsing.

Form 1:

  • py must be an expression of type Python
  • f must be the name of a function that is compatible with the specified parameter list, except that a single parameter of type Python is prepended. The function must return PyResult<T> for some T that implements ToPyObject.

Form 2:

  • py must be an identifier that refers to a Python value. The function body will also have access to a Python variable of this name.
  • f must be an identifier.
  • The function return type must be PyResult<T> for some T that implements ToPyObject.

§Errors

  • If argument parsing fails, the Rust function will not be called and an appropriate Python exception is raised instead (usually TypeError when the Python value does not match the expected type; the implementation of FromPyObject for your type may document additional errors).
  • If the Rust function panics, a Python SystemError will be raised.

§Example

use cpython::{Python, PyResult, PyErr, PyDict, py_fn};
use cpython::{exc};

fn multiply(py: Python, lhs: i32, rhs: i32) -> PyResult<i32> {
    match lhs.checked_mul(rhs) {
        Some(val) => Ok(val),
        None => Err(PyErr::new_lazy_init(py.get_type::<exc::OverflowError>(), None))
    }
}

fn main() {
    let gil = Python::acquire_gil();
    let py = gil.python();
    let dict = PyDict::new(py);
    dict.set_item(py, "multiply", py_fn!(py, multiply(lhs: i32, rhs: i32))).unwrap();
    py.run("print(multiply(6, 7))", None, Some(&dict)).unwrap();
}