有数据指针,需要Fortran顺序的Numpy数组。希望使用Cython。

4
这是一个我经常遇到的常见情况。我有一个返回双精度浮点数指针的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获取一些符号,而这些符号尚未被导入。肯定有更好的方法。


我已经在谷歌上搜索了很久,但没有发现明显的解决方案。也许我太蠢了。或者只是睡眠不足。干杯!


你解决了这个问题吗?我对一个好的答案很感兴趣。 - Nibor
不,我最终还是坚持使用了PyArray_NewFromDescr(...) - BrianTheLion
1
供日后参考:我自己编写了一个 define#define PyArray_SimpleNewFromDataF(nd, dims, typenum, data) PyArray_New(&PyArray_Type, nd, dims, typenum, NULL, data, 0, NPY_ARRAY_FARRAY, NULL) - Nibor
1个回答

2

这种方法有点取巧,但你可以颠倒维度的顺序然后返回转置。这样可以使得步幅正确,但不会复制数据。

cimport numpy as cnp
cnp.import_array()

cdef double a1[10]
for i in range(10):
    a1[i] = i

# C order
a2 = cnp.PyArray_SimpleNewFromData(2, [2, 5], cnp.NPY_FLOAT64, a1)
# fortran order
a3 = cnp.PyArray_SimpleNewFromData(2, [5, 2], cnp.NPY_FLOAT64, a1).T
# a2 and a3 point to the same data
a2[0,0] = 10.
print a2
print a3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接