python - 无法将多维数组传递给 *.pyx 中的 C 函数

标签 python c arrays numpy cython

我正在拼命尝试编写一个包装器来调用 C 函数:

  • 采用多个多维 C 连续数组作为输入
  • 在 C 例程中使用数组来执行某些操作

在我附加的代码中,我放置了两个我试图从 python 访问的函数。第一个函数 SurfInfo 调用 C 函数 PosAndTgtSurfVec,并且该函数按预期工作。为了使其工作,我使用了 this tutorial 。 问题出在调用 C 函数 SurfToSurf 的第二个包装函数 Surf2Surf 中。 请注意,我无法修改 C 函数。

代码如下:

import cython
cimport numpy as np
import numpy as np
from cython cimport view
from cpython cimport array

cdef extern void PosAndTgtSurfVec(double v[156],double X[18],double u[18]
     ,double t1[3],double t2[3],double (*a),double (*b),double (*xi),double (*theta)
     ,double s[3],double sxi[3],double stheta[3])

cdef extern void SurfToSurf(double v[5901],double X[2][12],double u[2][12]
     ,double t1[2][3],double t2[2][3],double a[2],double b[2],double hFG[4]
     ,double h[4],double R[24],double K[24][24])

# ---------------------------------------------------------#
# This one works ! 
def SurfInfo(
        np.ndarray[np.double_t, ndim=1, mode="c"] X,
        np.ndarray[np.double_t, ndim=1, mode="c"] u,
        np.ndarray[np.double_t, ndim=1, mode="c"] t1,
        np.ndarray[np.double_t, ndim=1, mode="c"] t2,
        double a,
        double b,
        double xi,
        double theta
       ):

    # declarations of pure C variables
    # used for output
    cdef :
        double v[156];
        double s[3];
        double sxi[3];
        double stheta[3];

    PosAndTgtSurfVec(v, &X[0], &u[0], &t1[0], &t2[0], &a, &b, &xi, &theta, s, sxi, stheta) 
    return s, sxi, stheta
# ---------------------------------------------------------#


# ---------------------------------------------------------#
# This one does not compile! 
def Surf2Surf(
    np.ndarray[double, ndim=2, mode="c"] X not None,
    np.ndarray[double, ndim=2, mode="c"] u,
    np.ndarray[double, ndim=2, mode="c"] t1,
    np.ndarray[double, ndim=2, mode="c"] t2,
    np.ndarray[double, ndim=1, mode="c"] a,
    np.ndarray[double, ndim=1, mode="c"] b,
    np.ndarray[double, ndim=1, mode="c"] hFG):

    cdef double v[5901]; 
    cdef double h[4]; 
    cdef double R[24]; 
    cdef double K[24][24];

    SurfToSurf(v, &X[0,0], &u[0,0], &t1[0,0], &t2[0,0], &a[0], &b[0], &hFG[0],h, R,K)
    return (h, R, K)
# ---------------------------------------------------------#

编译错误为:

SurfToSurf(v, &X[0,0], &u[0,0], &t1[0,0], &t2[0,0], &a[0], &b[0], &hFG[0],h, R,K)
                 ^
------------------------------------------------------------

wrp.pyx:54:18: Cannot assign type 'double *' to 'double (*)[12]'

如何提供所需的类型?我认为像在第一种情况下那样提供数组第一个元素的地址是可行的。 如果这个问题很愚蠢,我很抱歉,如果您可以将我重定向到可以帮助我解决问题的文档或示例,我会很高兴(我已经检查过 this linkthis book 但我肯定错过了那里的答案) 我暂时不找表演。

最佳答案

第二次尝试......

2D C arrays like double[2][12] are apparently stored as an array of double[12]s (即 convertible to a pointer to a double[12] )。因此它们实际上在内存中是连续的,因此应该与 C 连续 numpy 数组兼容(就像您传入的数组一样)。

您所要做的就是将 numpy 数组的第一个元素 double* 重新解释为指向 double[12]r 的指针。 (强制转换从来都不是理想的,因为它们通常会隐藏逻辑错误,但我认为在这种情况下没有其他选择):

# I'm using this instead of `cdef extern` just to provide an easy way
# of printing the elements and thus confirming that it works
cdef void SurfToSurf(double[2][12] x):
    for j in range(2):
        for i in range(12):

def Surf2Surf(np.ndarray[double, ndim=2, mode="c"] X):
    assert X.shape[0]>=2 and X.shape[1]==12

    SurfToSurf(<double (*)[12]>&X[0,0])
            print(x[j][i])

我添加了一个 assert 来检查数组的大小。如果没有它,如果通过 Python 接口(interface)传递的数组太小,您的程序就会面临崩溃的风险。

关于python - 无法将多维数组传递给 *.pyx 中的 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47103582/

相关文章:

python - 如何在Python中的数据框中获取打印函数输出

c - 编写不使用 IF 或 :? 条件运算符的程序

使用 C 在 Raspberry Pi 上设置时钟 gettime

c - 在 VirtualBox 内的 Debian 上调用 socket() 时出现错误 97

javascript - 对数组中的字符串进行排序

c - MPI 向其他处理器广播动态二维数组

python - 使用scikit-learn使用管道时出错

python - 有Python函数可以实现这个功能吗?

python - 使用 Openpyxl 将 IF 公式插入 excel 后出现 "@"符号

C++ win 32application : Employee Class array issue