После прочтения большого количества документации по numpy / cython я все еще не могу создать массив numpy из указателя в cython. Ситуация следующая. У меня есть файл Cython (* .pyx), содержащий функцию обратного вызова:
cimport numpy
cdef void func_eval(double* values,
int values_len,
void* func_data):
func = (<object> func_data)
# values.: contiguous array of length=values_len
array = ???
# array should be a (modifiable) numpy array containing the
# values as its data. No copying, no freeing the data by numpy.
func.eval(array)
В большинстве уроков и руководств рассматривается проблема превращения массива в указатель, но меня интересует обратное.
Я видел одно решение здесь , основанное на чистом python с использованием библиотеки ctypes (не то, что меня интересует). Сам Cython много говорит о типизированных видах памяти . Это также не совсем то, что я ищу, так как я хочу, чтобы все массивы работали над массивом.
Редактировать: A (слегка) измененный автономный MWE (сохранить как * 1014)*, скомпилируйте с помощью cython test.cyx
):
cimport numpy
cdef extern from *:
"""
/* This is C code which will be put
* in the .c file output by Cython */
typedef void (*callback)(double* values, int values_length);
void execute(callback cb)
{
double values[] = {0., 1.};
cb(values, 2);
}
"""
ctypedef void (*callback)(double* values, int values_length);
void execute(callback cb);
def my_python_callback(array):
print(array.shape)
print(array)
cdef void my_callback(double* values, int values_length):
# turn values / values_length into numpy array
# and call my_pytohn_callback
pass
cpdef my_execute():
execute(my_callback)
2-е редактирование:
Относительно возможного дубликата : Хотя вопросы связаны,первый ответ, как было указано, довольно хрупкий, опираясь на флаги данных памяти, которые, возможно, являются деталями реализации. Более того, вопрос и ответы довольно устарели, а API-интерфейс Cython расширяется с 2014 года. Однако, к счастью, я смог решить проблему самостоятельно.
Во-первых, вы можете привести необработанный указатель к типизированномуMemoryView работает с той же самой базовой памятью, не приобретая ее через
cdef double[:] values_view = <double[:values_length]> values
Однако этого недостаточно, поскольку, как я уже говорил, я хочу массив с массивами. Но есть возможность преобразовать MemoryView в массив numpy при условии, что он имеет тип данных numpy. Таким образом, цель может быть достигнута в одну строку с помощью
array = np.asarray(<np.float64_t[:values_length]> values)
. Можно легко проверить, что массив работает с правильным сегментом памяти, не имея его.