Создание пустого массива из указателя в Cython - PullRequest
0 голосов
/ 20 октября 2019

После прочтения большого количества документации по 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)

. Можно легко проверить, что массив работает с правильным сегментом памяти, не имея его.

...