I want a function that simply creates and returns a tuple as an example.
Basic template starting code (maturin new) looks like:
use pyo3::prelude::*;
/// Formats the sum of two numbers as string.
#[pyfunction]
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
Ok((a + b).to_string())
}
/// A Python module implemented in Rust.
#[pymodule]
fn tuple(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
Ok(())
}
I have tried something like this but can't figure out what combination of things is required to even compile.
#[pyfunction]
fn f_ret_tuple() -> PyResult<&'static PyTuple> {
let gil = Python::acquire_gil();
let py = gil.python();
let tuple: &PyTuple;
let elements: Vec<i32> = vec![0, 1, 2, 3, 4, 5];
tuple = PyTuple::new(py, elements);
Ok(tuple)
}
The problem is that the compiler can't prove your tuple will not outlive the GIL acquisition. But per the docs,
In a function or method annotated with
#[pyfunction]
or#[pymethods]
you can declare it as a parameter, and PyO3 will pass in the token when Python code calls it.
So:
#[pyfunction]
fn f_ret_tuple(py: Python<'_>) -> PyResult<&PyTuple> {
let tuple: &PyTuple;
let elements: Vec<i32> = vec![0, 1, 2, 3, 4, 5];
tuple = PyTuple::new(py, elements);
Ok(tuple)
}