Передача объекта Python в Rust

Я пытаюсь передать объект Python в ржавчину и выполнить операции, используя поля объекта Python.

Python:

class myclass(object):
    def __init__(self):
        self.a = 3

b = myclass()
print(b.a)
// 3

Ржавчина:

#[pyfn(m, "rust_obj")]
fn rust_obj_py(py: Python, x: PyObject) -> PyResult<PyObject> { 
    let y = x.clone_ref(py);
    y.a += 2;
    Ok(y)
}   

Ожидаемый результат при вызове из Python:

c = rust_obj(b)
print(c.a)
// 5

Вместо этого выдает ошибку Rust при компиляции:

error[E0609]: no field `a` on type `pyo3::PyObject`
   --> src\lib.rs:926:5
    |
926 |         y.a += 2;
    |           ^ unknown field

Есть ли способ перечислить поля и методы объекта в ржавчине и управлять полями?

1 ответ

Вы звоните clone_ref по y:

let y = x.clone_ref(py);

clone_ref возвращает другой PyObject. Тогда вы вызываете

y.a += 2;

И компилятор правильно говорит вам "нет поля a по типу pyo3::PyObject". Потому что PyObjectне раскрывает поля, которые вы ожидаете от объекта Python напрямую (это было бы сложно сделать, поскольку python динамически типизирован, тогда как rust - статически типизированный язык, поэтому все члены PyObject должны быть известны во время компиляции). В этих случаях документация полезна, чтобы узнать, как использовать PyObject. Там вы увидите, что у вас все еще есть доступa, но вы должны пройти через getattr метод. Чтобы сделать+= Я подозреваю, что лучше всего назвать python __iadd__ явно через call_method API.

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