Swig and multidimensional arrays

我们两清 提交于 2019-12-07 16:48:53

问题


I am using Swig to interface python with C code.

I want to call a C function that takes for argument a struct containing an int** var:

typedef struct
{
    (...)
    int** my2Darray;
} myStruct;

void myCFunction( myStruct struct );

I am struggling with multi dimensional arrays.

My code looks like this:

In the interface file, I am using carray like this:

%include carrays.i
%array_class( int, intArray );
%array_class( intArray, intArrayArray );

In python, I have:

myStruct = myModule.myStruct()
var = myModule.intArrayArray(28)

for j in range(28):
    var1 = myModule.intArray(28)

    for i in range(28):
        var1[i] = (...) filling var1 (...)

    var[j] = var1

myStruct.my2Darray = var

myCFonction( myStruct )

I get an error on the line myStruct.my2Darray = var:

TypeError: in method 'maStruct_monTableau2D_set', argument 2 of type 'int **'

I doubt about the line %array_class( intArray, intArrayArray ). I tried using a typedef for int* to create my array like this: %array_class( myTypeDef, intArrayArray ); But it didn't seem to work.

Do you know how to handle multidimensional arrays in Swig ?

Thanks for your help.


回答1:


Have you considered using numpy for this? I have used numpy with my SWIG-wrapped C++ project for 1D, 2D, and 3D arrays of double and std::complex elements with a lot of success.

You would need to get numpy.i and install numpy in your python environment.

Here is an example of how you would structure it:

.i file:

// Numpy Related Includes:
%{
#define SWIG_FILE_WITH_INIT
%}
// numpy arrays
%include "numpy.i"
%init %{
import_array(); // This is essential. We will get a crash in Python without it.
%}
// These names must exactly match the function declaration.
%apply (int* INPLACE_ARRAY2, int DIM1, int DIM2) \
      {(int* npyArray2D, int npyLength1D, int npyLength2D)}

%include "yourheader.h"

%clear (int* npyArray2D, int npyLength1D, int npyLength2D);

.h file:

/// Get the data in a 2D Array.
void arrayFunction(int* npyArray2D, int npyLength1D, int npyLength2D);

.cpp file:

void arrayFunction(int* npyArray2D, int npyLength1D, int npyLength2D)
{
    for(int i = 0; i < npyLength1D; ++i)
    {
        for(int j = 0; j < npyLength2D; ++j)
        {
            int nIndexJ = i * npyLength2D + j;
            // operate on array
            npyArray2D[nIndexJ];
        }
    }
}

.py file:

def makeArray(rows, cols):
    return numpy.array(numpy.zeros(shape=(rows, cols)), dtype=numpy.int)

arr2D = makeArray(28, 28)
myModule.arrayFunction(arr2D)



回答2:


This is how I handled 2d arrays. The trick I used was to write some inline code to handle the creation and mutation of an array. Once that is done, I can use those functions to do my bidding.

Below is the sample code.

ddarray.i

%module ddarray
%inline %{
// Helper function to create a 2d array
int* *int_array(int rows, int cols) {
    int i;
    int **arr = (int **)malloc(rows * sizeof(int *));
    for (i=0; i<rows; i++)
        arr[i] = (int *)malloc(cols * sizeof(int)); 
    return arr;
 }

void *setitem(int **array, int row, int col, int value) {
    array[row][col] = value;
    }
%}

ddarray.c

int calculate(int **arr, int rows, int cols) {
    int i, j, sum = 0, product;
    for(i = 0; i < rows; i++) {
        product = 1;
        for(j = 0; j < cols; j++)
            product *= arr[i][j];
        sum += product;
    }
    return sum;
}

Sample Python script

import ddarray

a = ddarray.int_array(2, 3)
for i in xrange(2):
    for j in xrange(3):
        ddarray.setitem(a, i, j, i + 1)

print ddarray.calculate(a, 2, 3)


来源:https://stackoverflow.com/questions/30259591/swig-and-multidimensional-arrays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!