Output values
We've gone deep into the weeds of how pyo3
handles arguments to your #[pyfunction]
s.
Let's now move our focus to output values: how do you return something from your Rust functions to Python?
IntoPy
Guess what? There's a trait for that too!
IntoPy
is the counterpart of FromPyObject
. It converts Rust values into Python objects:
#![allow(unused)] fn main() { pub trait IntoPy<T>: Sized { fn into_py(self, py: Python<'_>) -> T; } }
The output type of your #[pyfunction]
must implement IntoPy
.
IntoPy::into_py
IntoPy::into_py
expects two arguments:
self
: the Rust value you want to convert into a Python object.Python<'_>
: a GIL token that you can use to create new Python objects.
Case study: a newtype
Let's look at a simple example: a newtype that wraps a u64
.
We want it to be represented as a "plain" integer in Python.
#![allow(unused)] fn main() { use pyo3::prelude::*; struct MyType { value: u64, } impl IntoPy<Py<PyAny>> for MyType { fn into_py(self, py: Python<'_>) -> Py<PyAny> { self.value.to_object(py) } } }
Provided implementations
pyo3
provides out-of-the-box implementations of IntoPy
for many Rust types, as well as for all Py*
types.
Check out its documentation for an exhaustive list.
Exercise
The exercise for this section is located in 01_intro/06_output