【问题标题】:passing 2d array from numpy to c++ via swig can't use float**通过 swig 将 2d 数组从 numpy 传递到 c++ 不能使用 float**
【发布时间】:2011-01-11 17:57:38
【问题描述】:

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

我可以使用以下类型映射成功传入一维数组

(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 类型映射,我需要交错我的两个维度吗?我希望不是,有没有人成功地做到了这一点,你是怎么做的。

【问题讨论】:

    标签: c++ numpy swig


    【解决方案1】:

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

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

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

    使用浮点数**时,您的内存模型很可能是:

    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 中分配函数,这只是为了让您了解在两种格式之间进行转换。

    【讨论】:

    • 你不需要多次调用 malloc 来创建float**。只需初始化float* 的数组,使其指向二维数组中的每一行。
    • @Ben:我没有说它是强制性的,但是根据我的经验,很多人在使用 float** 时都会这样做,并且是一个数据示例,如果不先复制就绝对不能传递给 numpy .但是,转换函数完全使用您的建议(因为另一种方式也是可能的)
    • 您是否只是为convert 显示了错误的代码?您的回答说“不复制”,但代码无论如何都会复制。
    • @Ben:你当然是对的,转换功能不是我说的那样。我修复了代码以符合描述。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多