1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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
|
"""
ReadonlyArrayWrapper implements the buffer protocol to make the wrapped buffer behave as if
writeable, even for readonly buffers. This way, even readonly arrays can be passed as
argument of type (non const) memoryview.
This is a workaround for the missing support for const fused-typed memoryviews in
Cython < 3.0.
Note: All it does is LIE about the readonly attribute: tell it's false!
This way, we can use it on arrays that we don't touch.
!!! USE CAREFULLY !!!
"""
# TODO: Remove with Cython >= 3.0 which supports const memoryviews for fused types.
from cpython cimport Py_buffer
from cpython.buffer cimport PyObject_GetBuffer, PyBuffer_Release, PyBUF_WRITABLE
cimport numpy as cnp
cnp.import_array()
ctypedef fused NUM_TYPES:
cnp.npy_float64
cnp.npy_float32
cnp.npy_int64
cnp.npy_int32
cdef class ReadonlyArrayWrapper:
cdef object wraps
def __init__(self, wraps):
self.wraps = wraps
def __getbuffer__(self, Py_buffer *buffer, int flags):
request_for_writeable = False
if flags & PyBUF_WRITABLE:
flags ^= PyBUF_WRITABLE
request_for_writeable = True
PyObject_GetBuffer(self.wraps, buffer, flags)
if request_for_writeable:
# The following is a lie when self.wraps is readonly!
buffer.readonly = False
def __releasebuffer__(self, Py_buffer *buffer):
PyBuffer_Release(buffer)
def _test_sum(NUM_TYPES[::1] x):
"""This function is for testing only.
As this function does not modify x, we would like to define it as
_test_sum(const NUM_TYPES[::1] x)
which is not possible as fused typed const memoryviews aren't
supported in Cython<3.0.
"""
cdef:
int i
int n = x.shape[0]
NUM_TYPES sum = 0
for i in range(n):
sum += x[i]
return sum
|