如何为我的Rust结构体实现trait FromPyObject

5
考虑一个简单的 Rust 类通过 PyO3 暴露给 Python。
use pyo3::prelude::*;

#[pyclass(name=MyClass)]
pub struct PyMyClass {
  // Some fields
}

#[pymethods]
impl PyMyStruct {
  #[new]
  fn py_new(obj: PyRawObject) {
    obj.init({
      PyMyStruct {
        // ...
      }
    });
  }
}

现在有一个函数,应该以这两个结构体的方式从Python中调用:
a = MyStruct()
b = MyStruct()

c = foo(a,b)

因此,人们定义了
#[pyfunction]
fn foo(a: PyMyStruct, b: PyMyStruct) -> PyResult<PyMyStruct> {
  // some high performance logic implemented in rust ...
}

现在编译器声称PyMyStruct应该实现特质FromPyObject:
impl FromPyObject<'_> for PyMyStruct {
    fn extract(ob: &'_ PyAny) ->PyResult<Self> {
        // I dont know what to do here :(
    }
}

但我不知道如何从PyAny中检索出PyMyStruct的实例、指针或其他东西... 有人能帮我吗?

1个回答

2

我对这个木箱不太了解,但我认为你应该通过引用来获取你的对象。请注意,它们与Python解释器的其余部分共享,因此你实际上不能拥有它们。

也就是说,只需编写:

Original Answer翻译成"最初的回答"

#[pyfunction]
fn foo(a: &PyMyStruct, b: &PyMyStruct) -> PyResult<PyMyStruct> {
  // some high performance logic implemented in rust ...
}

如果你需要可变对象:

最初的回答:
#[pyfunction]
fn foo(a: &mut PyMyStruct, b: &mut PyMyStruct) -> PyResult<PyMyStruct> {
  // some high performance logic implemented in rust ...
}

这能够实现的原因是有这些实现: "FromPyObject"。
impl<'a, T> FromPyObject<'a> for &'a T where
    T: PyTryFrom<'a>
impl<'a, T> FromPyObject<'a> for &'a mut T where
    T: PyTryFrom<'a>,

最初的回答,然后是这个另一个:其他
impl<'v, T> PyTryFrom<'v> for T where
    T: PyTypeInfo

如果您在此函数中使用&mut变体并将同一对象传递两次,会发生什么?嗯,我不确定,但是浏览代码后,我猜你会得到对同一对象的两个&mut引用,因此会出现未定义行为。如果我是您,我会使用非mut变体,并在实际需要更改对象时使用RefCell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接