我想从 Python 调用返回 Python 对象的 Rust 函数:
my_rust_module.my_function() # => <object>
Run Code Online (Sandbox Code Playgroud)
我不确定如何创建这个函数,因为类实例化的 PYO3 指南描述了如何将这样的对象实例化为 a PyRef,但是我不知道如何从 a 返回这样的引用pyfunction。
这就是我正在尝试的:
#[pyfunction]
fn my_function(py: Python) -> PyRef {
let gil = Python::acquire_gil();
let py = gil.python();
PyRef::new(py, MyStruct { }).unwrap()
}
Run Code Online (Sandbox Code Playgroud)
但是,PyRef似乎不是有效的返回类型(编译器说“类型参数的数量错误:预期为 1,发现为 0”),并且我不知道如何将 a 转换PyRef为可以返回的内容,例如 a 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))
}
Run Code Online (Sandbox Code Playgroud)
或者:
#[pyfunction]
fn my_function() -> PyResult<Py<MyStruct>> {
let gil = Python::acquire_gil();
let py = gil.python();
Py::new(py, MyStruct {})
}
Run Code Online (Sandbox Code Playgroud)
我还冒昧地包装了返回的对象,PyResult以便将可能的错误传播到 python 领域。您可以用 Rust 解开包装并返回裸露的对象,但我认为建议采用这种处理错误的方式。
编辑:之前的答案并不完整,而且有点误导。最简单的方法实际上就是:
#[pyfunction]
fn my_function() -> PyResult<MyStruct> {
Ok(MyStruct {})
}
Run Code Online (Sandbox Code Playgroud)
您可以像普通的 Rust 结构一样使用 pyclass。
但是,如果正常实例化,则不能将 pyclass 视为 Python 对象。
为了获得包含 pyclass 的 Python 对象,我们必须使用一些特殊的方法。
我相信只有当所述值不跨越 Rust / Python 边界时这才是正确的。如果是,pyfunction宏会自动将 Python 对象转换为 Rust 值,并将 Rust 返回值转换回 Python 对象。PYO3 指南在这里可能更具体。
| 归档时间: |
|
| 查看次数: |
2277 次 |
| 最近记录: |