Примечание: Даже близко не к полному решению (по крайней мере, на данный момент!)
Я согласен с @DavidW, что, вероятно, будет лучше, если у одного непрерывного типа с типом памяти, напечатанного на Cython, естьвсе данные и данные копируются в него из ваших обзоров памяти python.Это верно, особенно если вы планируете создать гигантский вид памяти с типом cython только один раз, но планируете повторять его много раз.
Однако, вы могли бы получить указатель на содержимое вашего представления памяти python, используя PyMemoryView_GET_BUFFER
, чтобы получить базовый буфер, принадлежащий этому представлению памяти.Затем вы можете либо memcpy
данные в большую структуру данных (для более быстрого копирования), либо просто отслеживать массив указателей, причем каждый элемент указывает на данные просмотра памяти (который медленнее во время итерации, поскольку вы будетепереход по памяти из указателя буфера памяти в указатель буфера памяти).
Вот способ получить указатель на базовые данные объекта памяти Python.В папке cpython на cython github нет упоминания о PyMemoryView
, поэтому мне пришлось обернуть его вручную:
from cpython.object cimport PyObject
cdef extern from "Python.h":
Py_buffer* PyMemoryView_GET_BUFFER(PyObject *mview)
cdef object mv1 = memoryview(b'1234')
cdef Py_buffer* buf = PyMemoryView_GET_BUFFER(<PyObject*>mv1)
cdef char* buf_ptr = <char*>buf.buf
print(buf_ptr)#prints b'1234'
Обновление 1:
Не был уверен на 100%, как должна выглядеть структура трехмерного массива, поэтому я просто беру двумерный случай.Поскольку вы сказали, что не хотите вводить C ++, я создал этот тип данных array_t
, который ведет себя как вектор (ну, указатель на группу void*
).Много отвратительного шаблона, но здесь это идет:
from cpython.object cimport PyObject
from libc.stdlib cimport malloc, calloc, realloc, free
from libc.string cimport memcpy, memmove
cdef extern from "Python.h":
Py_buffer* PyMemoryView_GET_BUFFER(PyObject *mview)
cdef char* get_view_ptr(object view):
cdef Py_buffer* py_buf = PyMemoryView_GET_BUFFER(<PyObject*>view)
cdef char* ptr = <char*>py_buf.buf
return ptr
ctypedef struct array_t:
void** data
int max_items
int num_items
cdef void array_init(array_t* array):
array.data = NULL
array.max_items = 0
array.num_items = 0
cdef void array_add(array_t* array, void* item):
if array.max_items == 0:
array.max_items = 10
array.num_items = 0
array.data = <void**>calloc(array.max_items, sizeof(void*))
if array.max_items == array.num_items:
array.max_items *= 2
array.data = <void**>realloc(array.data, array.max_items * sizeof(void*))
array.data[array.num_items] = item
array.num_items += 1
cdef void array_set(array_t* array, int index, void *item):
if index < 0 or index >= array.max_items:
return
array.data[index] = item
cdef void* array_get(array_t* array, int index):
if index < 0 or index >= array.max_items:
return NULL
return array.data[index]
cdef void array_remove(array_t* array, int index):
cdef:
void* src
void* dest
if index < 0 or index >= array.max_items:
return
array.data[index] = NULL
if index+1 != array.max_items:
src = &array.data[index+1]
dest = &array.data[index]
memmove(dest, src, (array.max_items - index) * sizeof(void*))
array.num_items -= 1
cdef void array_free(array_t* array):
free(array.data)
cdef int i
cdef array_t a
cdef object mv1 = memoryview(b'12345')
cdef object mv2 = memoryview(b'67890')
cdef object mv3 = memoryview(b'abcde')
cdef object mv4 = memoryview(b'!@#$%')
array_init(&a)
array_add(&a, get_view_ptr(mv1))
array_add(&a, get_view_ptr(mv2))
array_add(&a, get_view_ptr(mv3))
array_add(&a, get_view_ptr(mv4))
for i in range(a.num_items):
print(i, <char*>array_get(&a, i))