add example for wrapping generic classes

This commit is contained in:
Bartosz Telenczuk 2024-02-02 17:16:23 +01:00 committed by Bartosz Telenczuk
parent 57735540e8
commit 64a6a02bf0
1 changed files with 30 additions and 0 deletions

View File

@ -82,6 +82,36 @@ When you need to share ownership of data between Python and Rust, instead of usi
A Rust `struct Foo<T>` with a generic parameter `T` generates new compiled implementations each time it is used with a different concrete type for `T`. These new implementations are generated by the compiler at each usage site. This is incompatible with wrapping `Foo` in Python, where there needs to be a single compiled implementation of `Foo` which is integrated with the Python interpreter.
Currently, the best alternative is to write a macro which expands to a new #[pyclass] for each instantiation you want:
```rust
# #![allow(dead_code)]
use pyo3::prelude::*;
struct GenericClass<T> {
data: T
}
macro_rules! create_interface {
($name: ident, $type: ident) => {
#[pyclass]
pub struct $name {
inner: GenericClass<$type>,
}
#[pymethods]
impl $name {
#[new]
pub fn new(data: $type) -> Self {
Self { inner: GenericClass { data: data } }
}
}
};
}
create_interface!(IntClass, i64);
create_interface!(FloatClass, String);
```
#### Must be Send
Because Python objects are freely shared between threads by the Python interpreter, there is no guarantee which thread will eventually drop the object. Therefore all types annotated with `#[pyclass]` must implement `Send` (unless annotated with [`#[pyclass(unsendable)]`](#customizing-the-class)).