grayfox57
grayfox57

Reputation: 31

Passing Python Object Into Rust

I am trying to pass a Python object into rust and perform operations using the fields of the Python object.

Python:

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

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

Rust:

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

Expected result when calling from Python would be:

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

Instead Rust error out when compiling:

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

Is there a way to list the object fields and methods in rust and manipulate the fields?

Upvotes: 3

Views: 1100

Answers (1)

zgerd
zgerd

Reputation: 1068

You are calling clone_ref on y:

let y = x.clone_ref(py);

clone_ref returns another PyObject. Then you're invoking

y.a += 2;

And the compiler correctly tells you "no field a on type pyo3::PyObject". Because PyObject doesn't expose the fields you would expect in a Python object directly (It would be difficuly to do so since python is dynamically typed whereas rust is a statically typed language, so all members of PyObject have to be known at compile-time). The documentation is helpful in these cases to learn how to use PyObject. There you'll see that you can still access a, but you have to go through the getattr method. In order to do the += I suspect you'd probably best call python's __iadd__ method explicitly through the call_method API.

Upvotes: 1

Related Questions