0

How does one unpack a python integer as a reference from a rust class method?

I'm trying to expose a rust struct to python but the interpreter complains about the reference to the i32.

This is the code:

#[pyclass]
pub struct DataMap {
    entries: HashMap<i32, DataEntry>,
}
#[pymethods]
impl DataMap {
    #[new]
    fn new() -> DataMap {
        DataMap {
            entries: HashMap::new(),
        }
    }
    fn insert(&mut self, key: i32, x: i32, y: i32) {
        let entry = DataEntry::new(x, y);
        self.entries.insert(key, entry);
    }
    fn get_entry(&self, key: &i32) -> Option<DataEntry> {
        if self.entries.contains_key(key) {
            Some(self.entries[key])
        } else {
            None
        }
    }
}

And this is the error:

  --> src/data_structure.rs:46:30
   |
46 |     fn get_entry(&self, key: &i32) -> Option<DataEntry> {
   |                              ^ the trait `PyClass` is not implemented for `&i32`
   |
   = help: the following other types implement trait `PyClass`:
             DataEntry
             DataMap
   = note: required for `&i32` to implement `FromPyObject<'_>`
   = note: required for `&i32` to implement `PyFunctionArgument<'_, '_>`
note: required by a bound in `extract_argument`
  --> /Users/gareth/.cargo/registry/src/github.com-1ecc6299db9ec823/pyo3-0.18.3/src/impl_/extract_argument.rs:86:8
   |
86 |     T: PyFunctionArgument<'a, 'py>,
   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`

It seems to be asking to implement the PyClass trait for i32, but I'm not sure how to do this in this context. My confusion stems from how references are handled between Python and Rust and how pyo3 should be used to implement this.

songololo
  • 4,724
  • 5
  • 35
  • 49

1 Answers1

2

My confusion stems from how references are handled between Python and Rust and how pyo3 should be used to implement this.

It's should not be, ask for an i32.

There is very little support for getting references out of python objects, because the layouts don't match, so getting a Rust object out of a Python one usually requires copying and reformatting the data. The only exceptions which ship with pyo3 are &str and &[u8] (and Cow<'a, [u8]>).

Plus that tends to be of limited use as it would preclude dropping the GIL, which is often what you want. Not to mention an &i32 just takes more resources than an i32, it's completely pointless.

Masklinn
  • 34,759
  • 3
  • 38
  • 57