如何实现使用PY03

时间:2019-12-05 23:46:22

标签: rust pyo3

我想从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

1 个答案:

答案 0 :(得分:3)

鉴于适当的脚手架已经到位,例如pymodulepyclass的定义,有多种方法可以实现此目的:

#[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 {})
}

The PYO3 pyclass guide状态:

  

您可以使用像普通的锈结构一样的pyclass。

     

但是,如果正常实例化,则不能将pyclass视为Python对象。

     

要获取包含pyclass的Python对象,我们必须使用一些特殊方法。

我相信只有在所述值未跨越Rust / Python边界时,这才是正确的。如果是的话,pyfunction宏会自动将Python对象转换为Rust值,并将Rust返回值转换回Python对象。 PYO3指南可能在这里更具体。