简体   繁体   English

如何使用 CFFI 将多维 Numpy 数组传递给 C 函数?

[英]How to pass multidimensional Numpy arrays to C function using CFFI?

I am trying to speed up my Python program by implementing a function in C++ and embedding it in my code using CFFI.我试图通过在 C++ 中实现一个函数并使用 CFFI 将其嵌入到我的代码中来加速我的 Python 程序。 The function takes two 3x3 arrays and computes a distance.该函数采用两个 3x3 数组并计算距离。 The Python code is the following: Python代码如下:

import cffi
import numpy as np

ffi = cffi.FFI()
ffi.cdef("""
    extern double dist(const double s[3][3], const double t[3][3]);
""")
lib = ffi.dlopen("./dist.so")

S = np.array([[-1.63538,  0.379116, -1.16372],[-1.63538, 0.378137, -1.16366 ],[-1.63193, 0.379116, -1.16366]], dtype=np.float32)
T = np.array([[-1.6467834, 0.3749715, -1.1484985],[-1.6623441, 0.37410975, -1.1647063 ],[-1.6602284, 0.37400728, -1.1496595 ]], dtype=np.float32)
Sp = ffi.cast("double(*) [3]", S.ctypes.data)
Tp = ffi.cast("double(*) [3]", T.ctypes.data)

dd = lib.dist(Sp,Tp);

This solution doesn't work as intended.此解决方案无法按预期工作。 Indeed the arguments printed by the C function are:实际上,C 函数打印的参数是:

 Sp=[[0.000002,  -0.270760,  -0.020458]
    [0.000002,  0.000000,  0.000000]
    [0.000000,  0.000000,  0.000000]]
 Tp=[[0.000002,  -0.324688,  -0.020588]
    [0.000002,  0.000000,  0.000000]
    [0.000000,  0.000000,  -nan]]

I have also tried the following to initialize the pointers:我还尝试了以下方法来初始化指针:

Sp = ffi.new("double *[3]")
for i in range(3):
    Sp[i] = ffi.cast("double *", S[i].ctypes.data)
Tp = ffi.new("double *[3]")
for i in range(3):
    Tp[i] = ffi.cast("double *", T[i].ctypes.data)
dd = lib.dist(Sp,Tp);

But this solution rises an error in dist(Sp,Tp) :但是这个解决方案在dist(Sp,Tp)一个错误:

TypeError: initializer for ctype 'double(*)[3]' must be a pointer to same type, not cdata 'double *[3]'

Do you have any idea on how to make it work?您对如何使其工作有任何想法吗? Thanks.谢谢。

The types double[3][3] and double *[3] are not equivalent.类型double[3][3]double *[3]不等价。 The former is an 2D array of double 3x3, stored as 9 contiguous double.前者是一个double 3x3的二维数组,存储为9个连续的double。 The latter is an array of 3 double pointers, which is not how 2D static arrays are implemented in C or C++.后者是一个包含 3 个双指针的数组,这不是在 C 或 C++ 中实现 2D 静态数组的方式。

Both numpy arrays and C++ static arrays are represented in memory as a contiguous block of elements, it's just the double *[3] type in the middle that's throwing a wrench in the works. numpy 数组和 C++ 静态数组在内存中都表示为一个连续的元素块,只是中间的double *[3]类型在工作中引发了问题。 What you'd want is to use double[3][3] proper or double[3]* (a pointer to a row of three doubles).您想要的是正确使用double[3][3]double[3]* (指向一行三个双打的指针)。 Note that if you use the latter you may need to change the function prototype to take double [][3] .请注意,如果您使用后者,您可能需要将函数原型更改为采用double [][3]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM