Commit edecc6c
committed
ENH: Add PEP 688 buffer protocol and fix np.asarray() lifetime safety
Add zero-copy data export to all wrapped itk.Image types via two
protocols, ensuring the exported array remains valid even after
the source image is deleted:
image = itk.imread("brain.nii.gz")
arr = np.asarray(image)
del image
print(arr[1,1,1]) # safe -- no crash
Protocol dispatch by Python version:
3.12+: np.asarray -> __buffer__ (PEP 688, zero-copy, memoryview
pins self via NDArrayITKBase intermediary)
3.10-11: np.asarray -> __array__ -> array_view_from_image (zero-copy,
NDArrayITKBase.itk_base holds reference to image)
Changes to pyBase.i:
- Add __buffer__() implementing PEP 688 buffer export with shaped
memoryview. Uses NDArrayITKBase as intermediary to hold a Python
reference to the image, preventing GC while any derived
memoryview/array exists.
- Simplify __array__() to always return zero-copy view via
array_view_from_image(). Supports NumPy 2.0 copy= parameter.
copy=True returns a plain ndarray (not NDArrayITKBase) so the
image can be GCd immediately.
- Remove __array_interface__ (returned raw pointer with no reference
holder -- use-after-free on del image, confirmed by test).
- Remove SIMULATE_PEP688 / SIMULATE_PEP688_DEBUG (confusing,
contradictory behaviors between __buffer__ and __array__ paths).
Changes to PyBuffer.i.init:
- Add _get_buffer_formatstring() with module-level _BUFFER_FORMAT_MAP
- Add _get_numpy_pixelid() with module-level _NUMPY_PIXELID_MAP
- Remove LD (long double) mapping (silent corruption)
Test suites added (121 assertions):
itkImageTest.py (29): __buffer__, memoryview, np.asarray, __array__
itkImageInteropTest.py (60): NumPy, PyTorch, Dask clinical sizes
itkImageLifetimeTest.py (32): del image on every export path
Supersedes InsightSoftwareConsortium#6020, InsightSoftwareConsortium#6018, InsightSoftwareConsortium#5673, InsightSoftwareConsortium#5665.
Co-Authored-By: Hans J. Johnson <hans-johnson@uiowa.edu>1 parent 35158b6 commit edecc6c
6 files changed
Lines changed: 1181 additions & 29 deletions
File tree
- Modules
- Bridge/NumPy/wrapping
- Core/Common/wrapping/test
- Wrapping/Generators/Python/PyBase
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
32 | 96 | | |
33 | 97 | | |
34 | 98 | | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
59 | 123 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
59 | 69 | | |
0 commit comments