我想从Python调用一个Rust函数,该函数返回一个Python对象:
my_rust_module.my_function() # => <object>
由于PYO3 guide on class instantiation描述了如何实例化诸如PyRef
的对象,因此我不确定如何创建此函数,但是我不知道如何从{返回这样的引用{1}}。
这是我正在尝试的:
pyfunction
但是,#[pyfunction]
fn my_function(py: Python) -> PyRef {
let gil = Python::acquire_gil();
let py = gil.python();
PyRef::new(py, MyStruct { }).unwrap()
}
似乎不是有效的返回类型(编译器说“类型参数数目错误:期望1,找到0”),而且我不知道如何转换{{1 }}转换为可以返回的内容,例如PyRef
。
答案 0 :(得分:3)
鉴于适当的脚手架已经到位,例如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 {})
}
我也自由地将返回的对象包装在PyResult
中,以便将可能的错误传播到python land。您可以在Rust中打开包装,然后返回裸对象,但是我建议您采用这种处理错误的方法。
编辑:上一个答案不完整,有点误导。最简单的方法实际上就是:
#[pyfunction]
fn my_function() -> PyResult<MyStruct> {
Ok(MyStruct {})
}
您可以使用像普通的锈结构一样的pyclass。
但是,如果正常实例化,则不能将pyclass视为Python对象。
要获取包含pyclass的Python对象,我们必须使用一些特殊方法。
我相信只有在所述值未跨越Rust / Python边界时,这才是正确的。如果是的话,pyfunction
宏会自动将Python对象转换为Rust值,并将Rust返回值转换回Python对象。 PYO3指南可能在这里更具体。