Skip to content

Commit 97d7b8d

Browse files
committed
WIP: add support for abi3t
1 parent 4ef0102 commit 97d7b8d

9 files changed

Lines changed: 176 additions & 41 deletions

File tree

src/array.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::error::{
2828
AsSliceError, BorrowError, DimensionalityError, FromVecError, IgnoreError, TypeError,
2929
DIMENSIONALITY_MISMATCH_ERR, MAX_DIMENSIONALITY_ERR,
3030
};
31-
use crate::npyffi::{self, npy_intp, NPY_ORDER, PY_ARRAY_API};
31+
use crate::npyffi::{self, _PyArray_GET_ITEM_DATA, npy_intp, NPY_ORDER, PY_ARRAY_API};
3232
use crate::slice_container::PySliceContainer;
3333
use crate::untyped_array::{PyUntypedArray, PyUntypedArrayMethods};
3434

@@ -1483,7 +1483,7 @@ impl<'py, T, D> PyArrayMethods<'py, T, D> for Bound<'py, PyArray<T, D>> {
14831483

14841484
#[inline(always)]
14851485
fn data(&self) -> *mut T {
1486-
unsafe { (*self.as_array_ptr()).data.cast() }
1486+
unsafe { (*_PyArray_GET_ITEM_DATA(self.as_array_ptr())).data.cast() }
14871487
}
14881488

14891489
#[inline(always)]

src/borrow/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ use crate::array::{PyArray, PyArrayMethods};
181181
use crate::convert::NpyIndex;
182182
use crate::dtype::Element;
183183
use crate::error::{AsSliceError, BorrowError};
184-
use crate::npyffi::flags;
184+
use crate::npyffi::{_PyArray_GET_ITEM_DATA, flags};
185185
use crate::untyped_array::PyUntypedArrayMethods;
186186

187187
use shared::{acquire, acquire_mut, release, release_mut};
@@ -537,7 +537,7 @@ where
537537
// SAFETY: consuming the only extant mutable reference guarantees we cannot invalidate an
538538
// existing reference, nor allow the caller to keep hold of one.
539539
unsafe {
540-
(*self.as_array_ptr()).flags &= !flags::NPY_ARRAY_WRITEABLE;
540+
(*_PyArray_GET_ITEM_DATA(self.as_array_ptr())).flags &= !flags::NPY_ARRAY_WRITEABLE;
541541
}
542542
self.into()
543543
}

src/borrow/shared.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ use rustc_hash::FxHashMap;
1515
use crate::array::get_array_module;
1616
use crate::cold;
1717
use crate::error::BorrowError;
18-
use crate::npyffi::{PyArrayObject, PyArray_Check, PyDataType_ELSIZE, NPY_ARRAY_WRITEABLE};
18+
use crate::npyffi::{
19+
_PyArray_GET_ITEM_DATA, PyArrayObject, PyArray_Check, PyDataType_ELSIZE, NPY_ARRAY_WRITEABLE,
20+
};
1921

2022
/// Defines the shared C API used for borrow checking
2123
///
@@ -57,7 +59,7 @@ unsafe extern "C" fn acquire_shared(flags: *mut c_void, array: *mut PyArrayObjec
5759
}
5860

5961
unsafe extern "C" fn acquire_mut_shared(flags: *mut c_void, array: *mut PyArrayObject) -> c_int {
60-
if (*array).flags & NPY_ARRAY_WRITEABLE == 0 {
62+
if (*_PyArray_GET_ITEM_DATA(array)).flags & NPY_ARRAY_WRITEABLE == 0 {
6163
return -2;
6264
}
6365

@@ -368,7 +370,7 @@ impl BorrowFlags {
368370

369371
fn base_address<'py>(py: Python<'py>, mut array: *mut PyArrayObject) -> *mut c_void {
370372
loop {
371-
let base = unsafe { (*array).base };
373+
let base = unsafe { (*_PyArray_GET_ITEM_DATA(array)).base };
372374

373375
if base.is_null() {
374376
return array as *mut c_void;
@@ -383,7 +385,7 @@ fn base_address<'py>(py: Python<'py>, mut array: *mut PyArrayObject) -> *mut c_v
383385
fn borrow_key<'py>(py: Python<'py>, array: *mut PyArrayObject) -> BorrowKey {
384386
let range = data_range(py, array);
385387

386-
let data_ptr = unsafe { (*array).data };
388+
let data_ptr = unsafe { (*_PyArray_GET_ITEM_DATA(array)).data };
387389
let gcd_strides = gcd_strides(array);
388390

389391
BorrowKey {
@@ -394,6 +396,7 @@ fn borrow_key<'py>(py: Python<'py>, array: *mut PyArrayObject) -> BorrowKey {
394396
}
395397

396398
fn data_range<'py>(py: Python<'py>, array: *mut PyArrayObject) -> (*mut c_char, *mut c_char) {
399+
let array = unsafe { _PyArray_GET_ITEM_DATA(array) };
397400
let nd = unsafe { (*array).nd } as usize;
398401
let data = unsafe { (*array).data };
399402

@@ -430,6 +433,7 @@ fn data_range<'py>(py: Python<'py>, array: *mut PyArrayObject) -> (*mut c_char,
430433
}
431434

432435
fn gcd_strides(array: *mut PyArrayObject) -> isize {
436+
let array = unsafe { _PyArray_GET_ITEM_DATA(array) };
433437
let nd = unsafe { (*array).nd } as usize;
434438

435439
if nd == 0 {

src/dtype.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ use pyo3::{
1717
};
1818

1919
use crate::npyffi::{
20-
self, NpyTypes, PyArray_Descr, PyDataType_ALIGNMENT, PyDataType_ELSIZE, PyDataType_FIELDS,
21-
PyDataType_FLAGS, PyDataType_NAMES, PyDataType_SUBARRAY, NPY_ALIGNED_STRUCT,
22-
NPY_BYTEORDER_CHAR, NPY_ITEM_HASOBJECT, NPY_TYPES, PY_ARRAY_API,
20+
self, _PyDataType_GET_ITEM_DATA, NpyTypes, PyArray_Descr, PyDataType_ALIGNMENT,
21+
PyDataType_ELSIZE, PyDataType_FIELDS, PyDataType_FLAGS, PyDataType_NAMES, PyDataType_SUBARRAY,
22+
NPY_ALIGNED_STRUCT, NPY_BYTEORDER_CHAR, NPY_ITEM_HASOBJECT, NPY_TYPES, PY_ARRAY_API,
2323
};
2424

2525
pub use num_complex::{Complex32, Complex64};
@@ -159,7 +159,7 @@ pub trait PyArrayDescrMethods<'py>: Sealed {
159159
/// [enumerated-types]: https://numpy.org/doc/stable/reference/c-api/dtype.html#enumerated-types
160160
/// [dtype-num]: https://numpy.org/doc/stable/reference/generated/numpy.dtype.num.html
161161
fn num(&self) -> c_int {
162-
unsafe { &*self.as_dtype_ptr() }.type_num
162+
unsafe { &*_PyDataType_GET_ITEM_DATA(self.as_dtype_ptr()) }.type_num
163163
}
164164

165165
/// Returns the element size of this type descriptor.
@@ -184,7 +184,9 @@ pub trait PyArrayDescrMethods<'py>: Sealed {
184184
///
185185
/// [dtype-byteorder]: https://numpy.org/doc/stable/reference/generated/numpy.dtype.byteorder.html
186186
fn byteorder(&self) -> u8 {
187-
unsafe { &*self.as_dtype_ptr() }.byteorder.max(0) as _
187+
unsafe { &*_PyDataType_GET_ITEM_DATA(self.as_dtype_ptr()) }
188+
.byteorder
189+
.max(0) as _
188190
}
189191

190192
/// Returns a unique ASCII character for each of the 21 different built-in types.
@@ -195,7 +197,9 @@ pub trait PyArrayDescrMethods<'py>: Sealed {
195197
///
196198
/// [dtype-char]: https://numpy.org/doc/stable/reference/generated/numpy.dtype.char.html
197199
fn char(&self) -> u8 {
198-
unsafe { &*self.as_dtype_ptr() }.type_.max(0) as _
200+
unsafe { &*_PyDataType_GET_ITEM_DATA(self.as_dtype_ptr()) }
201+
.type_
202+
.max(0) as _
199203
}
200204

201205
/// Returns an ASCII character (one of `biufcmMOSUV`) identifying the general kind of data.
@@ -206,7 +210,9 @@ pub trait PyArrayDescrMethods<'py>: Sealed {
206210
///
207211
/// [dtype-kind]: https://numpy.org/doc/stable/reference/generated/numpy.dtype.kind.html
208212
fn kind(&self) -> u8 {
209-
unsafe { &*self.as_dtype_ptr() }.kind.max(0) as _
213+
unsafe { &*_PyDataType_GET_ITEM_DATA(self.as_dtype_ptr()) }
214+
.kind
215+
.max(0) as _
210216
}
211217

212218
/// Returns bit-flags describing how this type descriptor is to be interpreted.
@@ -330,7 +336,7 @@ impl<'py> PyArrayDescrMethods<'py> for Bound<'py, PyArrayDescr> {
330336
}
331337

332338
fn typeobj(&self) -> Bound<'py, PyType> {
333-
let dtype_type_ptr = unsafe { &*self.as_dtype_ptr() }.typeobj;
339+
let dtype_type_ptr = unsafe { &*_PyDataType_GET_ITEM_DATA(self.as_dtype_ptr()) }.typeobj;
334340
unsafe { PyType::from_borrowed_type_ptr(self.py(), dtype_type_ptr) }
335341
}
336342

src/npyffi/array.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,22 @@ impl PyArrayAPI {
428428
// Min v2.0 impl_api![363; PyArray_CommonDType(dtype1: *mut PyArray_DTypeMeta, dtype2: *mut PyArray_DTypeMeta) -> PyArray_DTypeMeta];
429429
// Min v2.0 impl_api![364; PyArray_PromoteDTypeSequence(length: npy_intp, dtypes_in: *mut *mut PyArray_DTypeMeta) -> *mut PyArray_DTypeMeta];
430430
// Min v2.0 impl_api![365; _PyDataType_GetArrFuncs(descr: *const PyArray_Descr) -> *mut PyArray_ArrFuncs];
431+
// Slot 366, 367, 368 are the abstract DTypes
432+
}
433+
434+
// Min v2.5
435+
#[cfg(all(Py_LIMITED_API, Py_GIL_DISABLED))]
436+
impl PyArrayAPI {
437+
impl_api![369; _PyArray_GET_ITEM_DATA(arr: *const PyArrayObject) -> *mut PyArrayObject_fields];
438+
impl_api![370; _PyArrayIter_GET_ITEM_DATA(iter: *const PyArrayIterObject) -> *mut PyArrayIterObject_fields];
439+
impl_api![371; pub(crate) _PyArray_LegacyDescr_GET_ITEM_DATA(dtype: *const _PyArray_LegacyDescr) -> *mut _PyArray_LegacyDescr_fields];
440+
impl_api![372; _PyDataType_GET_ITEM_DATA(dtype: *const PyArray_Descr) -> *mut PyArray_Descr_fields];
441+
impl_api![373; _PyArrayMultiIter_GET_ITEM_DATA(multi: *const PyArrayMultiIterObject) -> *mut PyArrayMultiIterObject_fields];
442+
impl_api![374; _PyArrayNeighborhoodIter_GET_ITEM_DATA(iter: *const PyArrayNeighborhoodIterObject) -> *mut PyArrayNeighborhoodIterObject_fields];
443+
impl_api![375; _PyDatetimeScalarObject_GetMetadata(obj: *mut PyObject) -> *mut PyArray_DatetimeMetaData];
444+
impl_api![376; _PyTimedeltaScalarObject_GetMetadata(obj: *mut PyObject) -> *mut PyArray_DatetimeMetaData];
445+
impl_api![377; _PyDatetimeScalarObject_GetValue(obj: *mut PyObject) -> npy_datetime];
446+
impl_api![378; _PyTimedeltaScalarObject_GetValue(obj: *mut PyObject) -> npy_datetime];
431447
}
432448

433449
/// Checks that `op` is an instance of `PyArray` or not.

src/npyffi/mod.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,15 @@ pub fn is_numpy_2<'py>(py: Python<'py>) -> bool {
5858
macro_rules! impl_api {
5959
// API available on all versions
6060
[$offset: expr; $fname: ident ($($arg: ident: $t: ty),* $(,)?) $(-> $ret: ty)?] => {
61+
impl_api![$offset; pub $fname($($arg : $t), *) $(-> $ret)*];
62+
};
63+
[$offset: expr; $vis:vis $fname: ident ($($arg: ident: $t: ty),* $(,)?) $(-> $ret: ty)?] => {
6164
#[allow(non_snake_case)]
62-
pub unsafe fn $fname<'py>(&self, py: Python<'py>, $($arg : $t), *) $(-> $ret)* {
65+
$vis unsafe fn $fname<'py>(&self, py: Python<'py>, $($arg : $t), *) $(-> $ret)* {
6366
let f: extern "C" fn ($($arg : $t), *) $(-> $ret)* = self.get(py, $offset).cast().read();
6467
f($($arg), *)
6568
}
66-
};
69+
}
6770
}
6871

6972
// Define type objects associated with the NumPy API
@@ -82,6 +85,21 @@ macro_rules! impl_array_type {
8285
}
8386
}
8487

88+
// Until `extern type` is stabilized, use the recommended approach to
89+
// model opaque types:
90+
// https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
91+
#[cfg(all(Py_LIMITED_API, Py_GIL_DISABLED))]
92+
macro_rules! opaque_struct {
93+
($(#[$attrs:meta])* $pub:vis $name:ident) => {
94+
$(#[$attrs])*
95+
#[repr(C)]
96+
$pub struct $name {
97+
_data: (),
98+
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
99+
}
100+
};
101+
}
102+
85103
impl_array_type! {
86104
// Multiarray API
87105
// Slot 1 was never meaningfully used by NumPy

0 commit comments

Comments
 (0)