passing 2d array from numpy to c++ via swig can't use float**
I'm exploring wrapping c++ classes with SWIG and passing in data from numpy
I can sucessfully pass in a 1d array using the following typemap
(float*, IN_ARRAY1, int DIM1)
The size of the array is not known at compile time so I can't use the type map
(float, IN_ARRAY2[DIM1][DIM2])
the numpy.i help suggests using
(float开发者_Python百科*, IN_ARRAY2, int DIM1, int DIM2)
however my c++ class expects - a pointer to a pointer of floats
void Initialise(float** buffer, long dim1, long dim2)
to use the float* IN_ARRAY2 type map do I need to interleave my two dimensions? urg I hope not, has anyone managed to do this successfuly, what do you do.
You can't seemingly pass float** to numpy C API, because they are not compatible memory representations a priori.
In numpy, data in an array must be in one single contiguously memory region (there can be holes, but they must feet in one block as allocated by e.g. malloc):
data -> | - | - | - | ..... | - | # this is allocated in one block
a0 a1 a2 an
When using a float**, it is likely that your model of memory is:
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
}
That is, memory wise:
a -> | a[0] | -> | a[0][0] | a[0][1] | a[0][2] |
| a[1] | -> | a[1][0] | ....
This is actually almost always a bad format for numerical computation, because you cannot pass data in one block (bad for memory locality, etc...), and almost every numeric library worth its salt use that format. See e.g. this for an explanation.
Nevertheless, assuming you cannot modify your code, you can easily convert single block format to float** format without copying (the opposite is not possible):
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;
}
And you call this function as such
float **a;
convert((float*)numpy_data, n, m, &a);
Initialise(a, n, m);
It would actually be better not to allocate in the function from an API POV, this is just to give you an idea to convert between both formats.
Anyway if you pass an array as parameter you pass the pointer to first element of the array. And you must to know the array dimension to work with it.
精彩评论