Swig returning an array of paired

I know there are often many ways to solve certain problems. But here I know how I want to get it, but I can't get it to work with Python and SWIG ...

I have a C function that returns me an array of double values:

double *my(int x) { double a,b,*buf; buf = malloc (x * sizeof(double)); a=3.14; b=2.7; buf[0]=a; buf[1]=b; return buf; } 

Here I finally want to have an array as a return value. No, as in many examples, the "void" function, which is written to the input array. Now I would like to get a SWIG-python shell that can be used as:

 >>> import example >>> print example.my(7) [3.14,2.7] 

Whatever I do, I have some conceptual issues here - I always get s.th. e.g. <Swig Object of type 'double *' at 0xFABCABA12>

I tried to define some typemaps in my swg file:

 %typemap(out) double [ANY] { int i; $result = PyList_New($1_dim0); for (i = 0; i < $1_dim0; i++) { PyObject *o = PyFloat_FromDouble((double) $1[i]); PyList_SetItem($result,i,o); } } 

But still I can not get my results as needed. Does anyone have a simple code example to achieve this?

+8
c python arrays return swig
source share
5 answers

The first problem is that your type map does not match, you will need %typemap(out) double * { ... } , since your function returns a pointer to a double, not a double array.

If your list has a fixed size (i.e. an integer literal), as in the example you specified (which I assume is not what you want), you can simply change the type map as I indicated above and swap $1_dim0 for a fixed size.

Otherwise, your problem is that your %typemap(out) double * cannot know the value of your int x parameter. You can return a structure that contains both a pointer and a size. Then you can easily define a sample map to turn it into a list (or a NumPy array, see also my answer to the Wrap C struct with a member of the array to access in python: SWIG? Cython? Ctypes? ).

By the way, it is impossible to return an array with a fixed size in C (see also this answer: Declaring a C function to return an array ), so %typemap(out) double [ANY] { ... } will never match.

+4
source share

I had a similar problem and it was solved as follows.

 // example.i %module example %include "carrays.i" %array_class(float, floatArray); float * FloatArray(int N); float SumFloats(float * f); 

 # ipython > a = example.floatArray(23) # array generated by swig class constructor > a <example.floatArray; proxy of <Swig Object of type 'floatArray *' at 0x2e74180> > > a[0] -2.6762280573445764e-37 # unfortunately it is created uninitialized.. > b = example.FloatArray(23) # array generated by function > b <Swig Object of type 'float *' at 0x2e6ad80> > b[0] --------------------------------------------------------------------------- TypeError Traceback (most recent call last) # ..... TypeError: 'SwigPyObject' object is not subscriptable > #But there is a way to access b!! > p = example.floatArray_frompointer(b) # i found this function by example. and twice tab > p <example.floatArray; proxy of <Swig Object of type 'floatArray *' at 0x2e66750> > > p[0] 0.0 > p[0] = 42 > p[0] 42.0 

Fortunately, all of these types (float *, floatArray * and proxies for floatArray *) can be successfully passed to C ++ functions (e.g. SumFloats).

+3
source share

You might want to look at the documentation around carray.i:

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

http://www.swig.org/Doc2.0/Python.html#Python_nn48

+1
source share

If you don't mind pulling a numpy python module into your Python code, you can do the following:

In the SWIG interface file:

 %{ #define SWIG_FILE_WITH_INIT %} %include "numpy.i" %init %{ import_array(); %} %apply(float ARGOUT_ARRAY1[ANY]) {(float outarray1d[9])}; void rf(float outarray1d[9]); 

Only the last two lines refer to this example, the first element is used by default for numpy.i (see the numpy.i documentation elsewhere: http://docs.scipy.org/doc/numpy/reference/swig.interface-file .html ).

In the C file (can also be embedded in the .i file):

 void rf(float outarray1d[9]) { float _internal_rf[9]; /* ... */ memcpy(outarray1d, _internal_rf, 9*sizeof(float)); } 

Then you have a function that you can call from python as

 import mymodule a = mymodule.rf() # a is a numpy array of float32's, with len 9 

Now, if you do not want to be forced to drag out the numpy module in your python project, I suggest you check numpy.i to see how they do the% typemap trick - as I understand it, these are made using SWIG template types and are not bound essentially to numpy, - should be able to do the same trick with tuples or lists as the return value.

+1
source share

I don't know how much C you know - so apologize if I teach you to suck eggs here ...

There is no Array class in plain-ole C. An array is always a pointer to a piece of memory, not a β€œthing” in itself, and therefore cannot simply be printed out by itself.

In this case, your "buf" is of type "double *". AFAICRem, if you want to print the actual values ​​stored in the "memory pointed to by buf", you must free each of them, for example (in pseudo-code): for i = 0 for buflength print buf [i]

-3
source share

All Articles