@@ -182,6 +182,41 @@ impl DataType {
182
182
/// This means that all data types except for `DataType::Object` are assumed to be trivially copyable.
183
183
/// Furthermore, it is assumed that for `DataType::Object` the elements are pointers into the Python heap
184
184
/// and that the corresponding `Clone` implemenation will never panic as it only increases the reference count.
185
+ ///
186
+ /// # Custom element types
187
+ ///
188
+ /// You can implement this trait to manage arrays of custom element types, but they still need to be stored
189
+ /// on Python's heap using PyO3's [Py](pyo3::Py) type.
190
+ ///
191
+ /// ```
192
+ /// use numpy::{ndarray::Array2, DataType, Element, PyArray, PyArrayDescr, ToPyArray};
193
+ /// use pyo3::{pyclass, Py, Python};
194
+ ///
195
+ /// #[pyclass]
196
+ /// pub struct CustomElement;
197
+ ///
198
+ /// // The transparent wrapper is necessary as one cannot implement
199
+ /// // a foreign trait (`Element`) on a foreign type (`Py`) directly.
200
+ /// #[derive(Clone)]
201
+ /// #[repr(transparent)]
202
+ /// pub struct Wrapper(pub Py<CustomElement>);
203
+ ///
204
+ /// unsafe impl Element for Wrapper {
205
+ /// const DATA_TYPE: DataType = DataType::Object;
206
+ ///
207
+ /// fn is_same_type(dtype: &PyArrayDescr) -> bool {
208
+ /// dtype.get_datatype() == Some(DataType::Object)
209
+ /// }
210
+ /// }
211
+ ///
212
+ /// Python::with_gil(|py| {
213
+ /// let array = Array2::<Wrapper>::from_shape_fn((2, 3), |(_i, _j)| {
214
+ /// Wrapper(Py::new(py, CustomElement).unwrap())
215
+ /// });
216
+ ///
217
+ /// let _array: &PyArray<Wrapper, _> = array.to_pyarray(py);
218
+ /// });
219
+ /// ```
185
220
pub unsafe trait Element : Clone + Send {
186
221
/// `DataType` corresponding to this type.
187
222
const DATA_TYPE : DataType ;
0 commit comments