Решение:
Вручную реализовать буферный протокол:
Класс-оболочка, который упаковывает unsigned char**
и реализует буферный протокол (Indirect2DArray.pyx ):
cdef class Indirect2DArray:
cdef Py_ssize_t len
cdef unsigned char** raw_data
cdef ndim
cdef Py_ssize_t item_size
cdef Py_ssize_t strides[2]
cdef Py_ssize_t shape[2]
cdef Py_ssize_t suboffsets[2]
def __cinit__(self,int nrows,int ncols):
self.ndim = 2
self.len = nrows * ncols
self.item_size = sizeof(unsigned char)
self.shape[0] = nrows
self.shape[1] = ncols
self.strides[0] = sizeof(void*)
self.strides[1] = sizeof(unsigned char)
self.suboffsets[0] = 0
self.suboffsets[1] = -1
cdef set_raw_data(self, unsigned char** raw_data):
self.raw_data = raw_data
def __getbuffer__(self,Py_buffer * buffer, int flags):
if self.raw_data is NULL:
raise Exception("raw_data was NULL when calling __getbuffer__ Use set_raw_data(...) before the buffer is requested!")
buffer.buf = <void*> self.raw_data
buffer.obj = self
buffer.ndim = self.ndim
buffer.len = self.len
buffer.itemsize = self.item_size
buffer.shape = self.shape
buffer.strides = self.strides
buffer.suboffsets = self.suboffsets
buffer.format = "B" # unsigbed bytes
def __releasebuffer__(self, Py_buffer * buffer):
print("CALL TO __releasebuffer__")
Примечание. Я не смог передать необработанный указатель через конструктор оболочки, поэтому мне пришлось использовать отдельную функцию cdef для установки указателя
Вот его использование:
def test_wrapper(self):
cdef nrows= 10000
cdef ncols = 81
cdef unsigned char** raw_pointer = self.raw_data
wrapper = Indirect2DArray(nrows,ncols)
wrapper.set_raw_data(raw_pointer)
# now create the memoryview:
cdef unsigned char[::view.indirect_contiguous, ::1] view = wrapper
# print some slices
print(list(view[0,0:30]))
print(list(view[1,0:30]))
print(list(view[2,0:30]))
, производящий следующий вывод:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 1, 2, 3, 7, 8, 9, 1, 2, 3, 4, 5, 6, 2, 1, 4]
[2, 1, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 1, 2, 3, 7, 8, 9, 1, 2, 3, 4, 5, 6, 1, 2, 4]
[3, 1, 2, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 1, 2, 3, 7, 8, 9, 1, 2, 3, 4, 5, 6, 1, 2, 3]
Это именно то, что я ожидал.Спасибо всем, кто помог мне