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

Я пытаюсь передать объект 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

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


person grayfox57    schedule 22.02.2020    source источник


Ответы (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. Я подозреваю, что для того, чтобы выполнить +=, лучше всего явно вызвать метод __iadd__ Python через метод call_method API.

person zgerd    schedule 20.04.2020