如何使用 PY03 实现 returns 一个 Python 对象的 Rust 函数
How to implement a Rust function that returns a Python object using PY03
从 Python,我想调用一个 return 是 Python 对象的 Rust 函数:
my_rust_module.my_function() # => <object>
我不确定如何创建此函数,因为 PYO3 guide on class instantiation 描述了如何将此类对象实例化为 PyRef
,但是我不知道如何 return pyfunction
.
这样的引用
这就是我正在尝试的:
#[pyfunction]
fn my_function(py: Python) -> PyRef {
let gil = Python::acquire_gil();
let py = gil.python();
PyRef::new(py, MyStruct { }).unwrap()
}
但是,PyRef
似乎不是有效的 return 类型(编译器说 "wrong number of type arguments: expected 1, found 0"),我不知道如何转换 PyRef
变成可以 returned 的东西,例如 PyObject
.
如果有适当的脚手架,例如 pymodule
和 pyclass
定义,有多种方法可以实现此目的:
#[pyfunction]
fn my_function() -> PyResult<PyObject> {
let gil = Python::acquire_gil();
let py = gil.python();
let pyref = PyRef::new(py, MyStruct {})?;
Ok(pyref.to_object(py))
}
或者:
#[pyfunction]
fn my_function() -> PyResult<Py<MyStruct>> {
let gil = Python::acquire_gil();
let py = gil.python();
Py::new(py, MyStruct {})
}
我还冒昧地将 returned 对象包装在 PyResult
中,以便将可能的错误传播到 python 土地。您可以在 Rust 中展开并 return 裸对象,但我认为建议使用这种处理错误的方式。
编辑:之前的回答不完整,有点误导。最简单的方法其实就是:
#[pyfunction]
fn my_function() -> PyResult<MyStruct> {
Ok(MyStruct {})
}
You can use pyclasses like normal rust structs.
However, if instantiated normally, you can't treat pyclasses as Python objects.
To get a Python object which includes pyclass, we have to use some special methods.
我相信只有当上述值不跨越 Rust / Python 边界时,这才是正确的。如果是,pyfunction
宏会自动将 Python 对象转换为 Rust 值,并将 Rust return 值转换回 Python 对象。 PYO3 指南在这里可以更具体。
从 Python,我想调用一个 return 是 Python 对象的 Rust 函数:
my_rust_module.my_function() # => <object>
我不确定如何创建此函数,因为 PYO3 guide on class instantiation 描述了如何将此类对象实例化为 PyRef
,但是我不知道如何 return pyfunction
.
这就是我正在尝试的:
#[pyfunction]
fn my_function(py: Python) -> PyRef {
let gil = Python::acquire_gil();
let py = gil.python();
PyRef::new(py, MyStruct { }).unwrap()
}
但是,PyRef
似乎不是有效的 return 类型(编译器说 "wrong number of type arguments: expected 1, found 0"),我不知道如何转换 PyRef
变成可以 returned 的东西,例如 PyObject
.
如果有适当的脚手架,例如 pymodule
和 pyclass
定义,有多种方法可以实现此目的:
#[pyfunction]
fn my_function() -> PyResult<PyObject> {
let gil = Python::acquire_gil();
let py = gil.python();
let pyref = PyRef::new(py, MyStruct {})?;
Ok(pyref.to_object(py))
}
或者:
#[pyfunction]
fn my_function() -> PyResult<Py<MyStruct>> {
let gil = Python::acquire_gil();
let py = gil.python();
Py::new(py, MyStruct {})
}
我还冒昧地将 returned 对象包装在 PyResult
中,以便将可能的错误传播到 python 土地。您可以在 Rust 中展开并 return 裸对象,但我认为建议使用这种处理错误的方式。
编辑:之前的回答不完整,有点误导。最简单的方法其实就是:
#[pyfunction]
fn my_function() -> PyResult<MyStruct> {
Ok(MyStruct {})
}
You can use pyclasses like normal rust structs.
However, if instantiated normally, you can't treat pyclasses as Python objects.
To get a Python object which includes pyclass, we have to use some special methods.
我相信只有当上述值不跨越 Rust / Python 边界时,这才是正确的。如果是,pyfunction
宏会自动将 Python 对象转换为 Rust 值,并将 Rust return 值转换回 Python 对象。 PYO3 指南在这里可以更具体。