문제

I'm using SWIG with numpy.i to expose a C library to python. The function I'm trying to wrap takes a series of double arrays as arguments:

int wcsp2s(struct wcsprm *wcs, int ncoord, int nelem, const double pixcrd[], double imgcrd[], double phi[], double theta[], double world[], int stat[]);

where some of the arrays are actually two-dimensional, with the extent given by the ncoord and nelem arguments. It's these two-dimensional arrays I'm having trouble with, since numpy.i only seems to support things of the form int n1,int n2,double * arr or various permutations (and my C function does not want those extra integers), or double arr[ANY][ANY]. The latter looked promising, as a multidimensional C array is just a contiguous block of memory, and so should be compatible with what the function expects. But when I try

%apply (double INPLACE_ARRAY2[ANY][ANY]) {(double imgcrd[]),(double world[])};

SWIG (or rather gcc running on SWIG's output) complains:

wcs_wrap.c:3770:7: error: expected expression before ‘,’ token

Here SWIG has generated invalid C code for those arguments.

Is what I'm trying to do here possible? I guess I could use %inplace and %rename to create a wrapper function that does take in the (unnecessary) dimensions of the arrays, and then calls the real function. Even better than the approach above with inplace arrays would be if I could return these arrays as output arguments (their dimensions are easy to calculate based on ncoord and nelem.

Or perhaps a fast (i.e. not the one in astLib) python interface to libwcs already exists, so I don't have to do this?

Edit: I just discovered pywcs (which has such an obvious name that i should have found it during my initial search), which solves my underlying problem.

Edit2: I guess a wrapper that takes in a 2d numpy arrays ans passes on a flattened view of it would get around the problem, since 1d arrays seem to work. Still, that ends up requiring a large amount of files for a simple wrapper (.i, _wrap.c, .py from swig and an additional .py to further wrap the SWIG functions to fix the dimensionality problem.

도움이 되었습니까?

해결책

I am also missing a good cookbook for using numpy.i. As far as I understand, you can either:

  • pass arrays of dynamic size, where you pass the dimensions as function parameters as well. If your function behaves differently, write a wrapper (e.g., IN_ARRAY2 or INPLACE_ARRAY2).
  • pass arrays of fixed size (e.g., IN_ARRAY2 or INPLACE_ARRAY2).
  • When returning arrays (e.g., ARGOUT_ARRAY1), you have to pass the size when calling it from python. In the example below, you would write oo = func3(20). The reason seems to be since python needs to allocate the memory, it needs to know about the size,

For example, your .i-file could look like his:

...
%include "numpy.i"

%init %{
  import_array();
%}

// Pass  array of dynamic size:
%apply (double* INPLACE_ARRAY2, int DIM1, int DIM2) {(double *xx, int xx_n, int xx_m)};
void func1(double *xx,int xx_n, int xx_m);

// Pass array of fixed size:
%apply (int *INPLACE_ARRAY2[ANY][ANY]) { (double yy[4][4]) };
void func2(double yy[4][4]);

// Return a dynamic 1D array:
%apply (double* ARGOUT_ARRAY1, int DIM1) {(double* out, int out_n)}
void func3(double* out, int out_n);

Of course you can combine these - check the Docs for more information

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top