Skip to content

Commit

Permalink
Merge pull request PyO3#3789 from btel/patch-1
Browse files Browse the repository at this point in the history
docs: add example for wrapping generic classes
  • Loading branch information
davidhewitt committed Feb 5, 2024
2 parents 02f1df6 + 64a6a02 commit ecb4ecb
Showing 1 changed file with 30 additions and 0 deletions.
30 changes: 30 additions & 0 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
Expand Down

0 comments on commit ecb4ecb

Please sign in to comment.