4

考虑一个通过 pyo3 暴露给 python 的简单 rust 类

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应该实现 trait FromPyObject

impl FromPyObject<'_> for PyMyStruct {
    fn extract(ob: &'_ PyAny) ->PyResult<Self> {
        // I dont know what to do here :(
    }
}

但我不知道如何PyMyStructPyAny...检索实例、指针或其他任何东西。有人可以帮我吗?

4

1 回答 1

2

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

也就是说,只需编写:

#[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 ...
}

这是有效的,因为有这些 impls

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变体并使用 a 。RefCell

于 2019-07-21T10:47:32.363 回答