Как реализовать черту FromPyObject для моей структуры ржавчины

Рассмотрим простой класс ржавчины, доступный через 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 :(
    }
}

Но я не знаю, как получить экземпляр, указатель или что-то из PyMyStruct из PyAny... Кто-нибудь может мне помочь?

1 ответ

Я мало что знаю об этом ящике, но думаю, что вы должны брать свои объекты по ссылке. Обратите внимание, что они используются совместно с остальной частью интерпретатора 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 ...
}

Это работает, потому что есть следующие имплименты:

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 если вы действительно хотите изменить объект.

Другие вопросы по тегам