Minimal example that works but isn't quite what I want:
use std::collections::HashMap;
use pyo3::class::basic::CompareOp;
use pyo3::class::PyObjectProtocol;
use pyo3::prelude::*;
#[pyclass]
struct MyStruct {
foo: HashMap<i32, Vec<i32>>,
}
#[pyproto]
impl PyObjectProtocol for MyStruct {
fn __richcmp__(&self, other: PyRef<MyStruct>, op: CompareOp) -> Py<PyAny> {
let gil = Python::acquire_gil();
let py = gil.python();
if let CompareOp::Eq = op {
let other_foo = &(other.foo);
let res = self.foo == *other_foo;
return res.into_py(py);
}
py.NotImplemented();
}
}
So this will take a reference to a MyStruct
living in the python heap and run the comparison on it, and my understanding is that no copying / cloning will happen.
But this isn't quite the pythonic way. The argument other
doesn't have to be of the same type. Instead of raising a TypeError
, the comparison method should just return NotImplemented
.
I'm trying to change the signature so that
- I can accept arbitrary python objects. I thought
&PyAny
would be just right - I can then check the type, or try the conversion, but without cloning the object from the Python heap over to Rust's heap.
Is there any way to convert, with checking of course, a &PyAny
into a
PyRef<MyStruct>
?