我在C
中有代码,我想在python
中使用,我使用 SWIG 来包装C代码,并成功导入python模块在我的python代码中。
现在我有以下代码:
import flame
import numpy as np
data = np.random.rand(3,2).astype(np.float32, copy=False)
N = 3
M = 2
print data
flameobject = flame.Flame_New()
flame.Flame_SetDataMatrix( flameobject, data, N, M, 0 )
这会产生错误:
TypeError: in method 'Flame_SetDataMatrix', argument 2 of type 'float *[]'
我知道我应该将float array pointer
传递给方法,但是如何将我的Numpy多维数组转换为正确的类型呢?
答案 0 :(得分:1)
有关于此的SciPy文档:如何通过SWIG将numpy数组传递给C代码(反之亦然)。看看here。
基本上,您可以通过以下方式使用swig接口文件numpy.i
。在swig界面文件中,您包括:
%{
#define SWIG_FILE_WITH_INIT
%}
%include "numpy.i"
%init %{
import_array();
%}
然后在提到C函数之前添加你的接口文件:
%apply ( float* IN_ARRAY2, int DIM1, int DIM2 ) {
(float* your_array_parameter_name, int N_parameter_name, int M_parameter_name)
};
这适用于普通的C float
数组。我不太确定float* []
是什么。您可能需要为此编写自己的类型映射,您可以使用numpy.i
提供的实用程序宏。但是在上面提到的numpy.i文档或相关的swig typemap docs
答案 1 :(得分:0)
对于那些可能面临同样问题的人来说,这就是我最终解决的问题。
首先,我更改了.h
文件中的标题和
.c
文件
void Flame_SetDataMatrix( Flame *self, float *data[], int N, int M, int T );
到
void Flame_SetDataMatrix( Flame *self, float *data, int N, int M, int T );
之后,我添加了
%apply (float* IN_ARRAY2, int DIM1, int DIM2) {
(float *data, int N, int M)
};
到接口文件(flame.i
)。这样就可以像这样调用 Python 中的函数:flame.Flame_SetDataMatrix( flameobject, data, T)
,其中data是一个带有两个维度的 numpy 数组。
“问题”现在是到达C函数的数组格式错误,因为我们需要一个double数组(在这种情况下是一个指向float的指针)。
解决方案是转换这个包含在单个维度中的数组,以重建c代码中的double数组,如下所示:
//n = number of rows, m= number of columns columns
void Flame_SetDataMatrix( Flame *self, float *data, int n, int m, int dt )
{
//convert data to float** for later use
int i=0, j=0;
float ** data2 = (float**) calloc( n, sizeof(float*) );
for (i=0; i<n; i++){
data2[i] = calloc( m, sizeof(float) );
for (j=0; j<m; j++){
//the data is in a single array row after row, so i*columns+j
data2[i][j] = data[i * m + j];
}
}
最后,我可以使用相同的“技巧”来将二维浮点数组放回到一个numpy数组中,我确实需要重新编译,但是在numpy中很容易。
希望它会对某人有所帮助。