这是一个我经常遇到的常见情况。我有一个返回双精度浮点数指针的C函数:
//myheader.h
double *mycfuntion(...)
我知道返回的数据的维度。我还知道这些数据是按照Fortran顺序排列的。我想编写一个Cython“shim”,将数据作为Numpy数组传递给Python:
#myshim.pyx
import numpy
cimport numpy as cnumpy
cnumpy.import_array()
cdef extern from "myheader.h" :
double *mycfunction(...)
def mypyfunc(...) :
cdef double *data = mycfunction(...)
**MAGIC**
return outarray
MAGIC 理念
(A) cdef cnumpy.ndarray[cnumpy.double_t, mode='fortran', ...] outarray
这是最方便的方法。但是,我在如何将指针data
转换为缓冲区以传递给cnumpy.ndarray构造函数方面遇到了一些关键问题。我已经尝试过:
cdef cnumpy.ndarray[ cnumpy.double_t, mode='fortran', ...] outarray
cdef bytes databuffer = <char *>data
outarray = numpy.ndarray(buffer=databuffer, dtype=numpy.double, ...)
这种方法经常会出现TypeError: buffer is too small for requested array
错误。
(B) Numpy C-API
我经常在Cython中使用cnumpy.PyArray_SimpleNewFromData(...)
,它运行良好。问题在于它不支持flags参数,因此我无法告诉它构建Fortran数组。在纯C实现中我使用的替代方法是PyArray_NewFromDescr(...)
。它接受flags。这种方法繁琐且痛苦,意味着需要通过extern
块从numpy获取一些符号,而这些符号尚未被导入。肯定有更好的方法。
我已经在谷歌上搜索了很久,但没有发现明显的解决方案。也许我太蠢了。或者只是睡眠不足。干杯!
PyArray_NewFromDescr(...)
。 - BrianTheLiondefine
:#define PyArray_SimpleNewFromDataF(nd, dims, typenum, data) PyArray_New(&PyArray_Type, nd, dims, typenum, NULL, data, 0, NPY_ARRAY_FARRAY, NULL)
- Nibor