【问题标题】:Transferring arrays from c to python将数组从 c 传输到 python
【发布时间】:2015-11-09 11:40:08
【问题描述】:

我正在将 double-array 从 c-function 转移到 python-function。我的代码是:
C代码:

double *compute(int size, const double a[])
{
    double* array;
    array = malloc(sizeof(double)*size);
    for (int i=0; i<size; i++)
    {
    array[i] = 3*a[i];
    }
    //printf("Array in compute-function is: \n[");
    //for(int i = 0; i < size; i++)
        //printf("%f, ", array[i]);
    //printf("]\n");
    return array;
}

pyx 代码:

cdef class ArrayWrapper:
    cdef void* data_ptr
    cdef int size

    cdef set_data(self, int size, void* data_ptr):
        """ Set the data of the array
        This cannot be done in the constructor as it must recieve C-level
        arguments.
        Parameters:
        -----------
        size: int
            Length of the array.
        data_ptr: void*
            Pointer to the data            
        """
        self.data_ptr = data_ptr
        self.size = size

    def __array__(self):
        """ Here we use the __array__ method, that is called when numpy
            tries to get an array from the object."""
        cdef np.npy_intp shape[1]
        shape[0] = <np.npy_intp> self.size
        # Create a 1D array, of length 'size'
        ndarray = np.PyArray_SimpleNewFromData(1, shape,
                                               np.NPY_INT, self.data_ptr)
        return ndarray

    def __dealloc__(self):
        """ Frees the array. This is called by Python when all the
        references to the object are gone. """
        free(<void*>self.data_ptr)


def py_compute(int size, np.ndarray[np.double_t,ndim=1] a):
    """ Python binding of the 'compute' function in 'GNLSE_RHS.c' that does
        not copy the data allocated in C.
    """
    cdef double *array
    cdef np.ndarray ndarray
    # Call the C function
    array = compute(size, <double*> a.data)

    array_wrapper = ArrayWrapper()
    array_wrapper.set_data(size, <void*> array) 
    ndarray = np.array(array_wrapper, copy=False)
    # Assign our object to the 'base' of the ndarray object
    ndarray.base = <PyObject*> array_wrapper
    # Increment the reference count, as the above assignement was done in
    # C, and Python does not know that there is this additional reference
    Py_INCREF(array_wrapper)


    return ndarray

python代码:

for i in xrange(10):
    x[i] = i;

a = cython_wrapper.py_compute(10, x)
print a

但我的结果是

[         0          0          0 1074266112          0 1075314688          0 1075970048          0 1076363264]

而不是预期的

[  0.   3.   6.   9.  12.  15.  18.  21.  24.  27.]

我的错误在哪里?我认为这与有问题的指针传输有关,但我不确定。

【问题讨论】:

    标签: python c python-2.7 cython


    【解决方案1】:

    这里的错误是在这一行

    ndarray = np.PyArray_SimpleNewFromData(1, shape,
                                          np.NPY_INT, self.data_ptr)
    

    你告诉 numpy self.data_ptr 指向一个整数数组,不是双精度数之一。

    您可以通过告诉 numpy 正确的数据类型来修复您的代码,如下所示:

    ndarray = np.PyArray_SimpleNewFromData(1, shape,
                                          np.NPY_DOUBLE, self.data_ptr)
    

    它应该按预期工作。

    除此之外,您还可以通过不必传递输入数组的大小来稍微简化包装器代码,因为它已经包含在您传递给 py_computenp.ndarray

    def py_compute(np.ndarray[np.double_t,ndim=1] a):
        """ Python binding of the 'compute' function in 'GNLSE_RHS.c' that does
            not copy the data allocated in C.
        """
        cdef double *array
        cdef np.ndarray ndarray
        cdef size = a.shape[0]
    
        # Call the C function
        array = compute(size, &a[0])
    
        array_wrapper = ArrayWrapper()
        array_wrapper.set_data(size, <void*> array) 
        ndarray = np.array(array_wrapper, copy=False)
        # Assign our object to the 'base' of the ndarray object
        ndarray.base = <PyObject*> array_wrapper
        # Increment the reference count, as the above assignement was done in
        # C, and Python does not know that there is this additional reference
        Py_INCREF(array_wrapper)
    
    
        return ndarray
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-01
      • 1970-01-01
      • 2011-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多