通过swig将2d数组从numpy传递到c ++不能使用float **

时间:2011-01-11 17:57:39

标签: c++ numpy swig

我正在探索使用SWIG包装c ++类并从numpy传递数据

我可以使用以下typemap成功传入1d数组

(float*, IN_ARRAY1, int DIM1)

在编译时不知道数组的大小,所以我不能使用类型映射

(float, IN_ARRAY2[DIM1][DIM2])

numpy.i帮助建议使用

(float*, IN_ARRAY2, int DIM1, int DIM2)

但是我的c ++类需要 - 指向浮点数的指针

void Initialise(float** buffer, long dim1, long dim2)

使用float * IN_ARRAY2类型的地图我需要交错我的两个维度吗?我希望不是,有没有人成功地做到了这一点,你做了什么。

2 个答案:

答案 0 :(得分:2)

你似乎无法将float **传递给numpy C API,因为它们不是先验的兼容内存表示。

在numpy中,数组中的数据必须位于一个连续的内存区域中(可能存在漏洞,但它们必须位于一个块中,例如由malloc分配):

data -> | - | - | - | ..... | - | # this is allocated in one block
         a0  a1  a2          an

使用float **时,你的内存模型可能是:

float** a;
int n = 10, m = 20; // n,m matrix

a = malloc(sizeof(*a) * n) // ten rows
for (int i=0; i < n; ++i) {
    a[i] = malloc(sizeof(*a[i]) * m); // one row of 29 items
}

那就是记忆:

a -> | a[0] | -> | a[0][0] | a[0][1] | a[0][2] | 
     | a[1] | -> | a[1][0] | ....

这实际上几乎总是一种糟糕的数值计算格式,因为你不能在一个块中传递数据(对于内存局部性等不好......),而且几乎每个值得盐的数字库都使用这种格式。参见例如this获得解释。

尽管如此,假设您无法修改代码,您可以轻松地将单个块格式转换为float **格式而无需复制(相反的情况不可能):

void convert(float *in, int n, int m, float ***out)
{
    float **data;
    int i;

    data = malloc(sizeof(*data) * n);
    for(i = 0; i < n; ++i) {
            data[i] = in + i * m:
    }       

    *out = data;
}

你将此功能称为

float **a;
convert((float*)numpy_data, n, m, &a);

Initialise(a, n, m);

实际上最好不要从API POV中分配函数,这只是为了让您在两种格式之间进行转换。

答案 1 :(得分:0)

无论如何,如果将数组作为参数传递,则将指针传递给数组的第一个元素。你必须知道数组维度才能使用它。