7

I have a struct + implementation in Rust that I return to Python. This object can also be passed back to Rust for further work. (In my actual code, I'm using a HashMap<String, MyStruct>, but even just using a struct directly seems to cause the same issues, so my example uses struct Person for simplicity.)

It appears that I need to impl FromPyObject for Person, but Rust can't find PyAny's downcast method

#[pyclass]
struct Person {
    name: String,
    age: u8,
    height_cm: f32,
}

impl pyo3::FromPyObject<'_> for Person {
    fn extract(any: &PyAny) -> PyResult<Self> {
        Ok(any.downcast().unwrap())
               ^^^^^^^^ method not found in `&pyo3::types::any::PyAny`
    }
}

#[pyfunction]
fn make_person() -> PyResult<Person> {
    Ok(Person {
        name: "Bilbo Baggins".to_string(),
        age: 51,
        height_cm: 91.44,
    })
}

#[pyfunction]
fn person_info(py:Python, p: PyObject) -> PyResult<()> {
    let p : Person = p.extract(py)?;
    println!("{} is {} years old", p.name, p.age);
    Ok(())
}

Is this the right way to pass a Rust object from Python back into Rust? If so, what's the right way to use PyAny here?

user655321
  • 1,572
  • 2
  • 16
  • 33
  • 1
    This method doesn't seem to exist in any released version. You are looking at the master branch of the code, but you are probably using a released version. I recommend looking at the version of the code that you are actually using, or maybe at the documentation. – Sven Marnach Mar 05 '20 at 23:53
  • 1
    The PR introducing `downcast` was merged four days ago: https://github.com/PyO3/pyo3/pull/770/files#diff-744ca591f3f85be1802380369bb5b42e – Sven Marnach Mar 05 '20 at 23:55
  • Arg, you're right. [`any.rs` for v0.9.0-alpha.1](https://github.com/PyO3/pyo3/blob/d2174c2eadab7879255a6be51046eff83e22e646/src/types/any.rs#L38) (the current release) has `downcast_ref` and `downcast_mut`. Using that, I can get a reference as `let x : &Person = any.downcast_ref().unwrap();`. I assumed that I could also somehow take ownership again, but perhaps this is impossible (with Python having a reference as well), so I do have to apparently create a new value. – user655321 Mar 06 '20 at 00:04

0 Answers0