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