[Swig-user] convert double* returned value to 3-length numpy array

28 views
Skip to first unread message

David Froger

unread,
Mar 22, 2012, 5:17:54 AM3/22/12
to swig-user
Dear Swig user,

I have a C++ header like this:
class A{
public:
A();
A(const double& x, const double& y, const double& z);
~A();

void initialize(const double& x, const double& y, const double& z);

double* get_vec(void); /* return a pointer to vec_ */
const double* get_vec(void) const; /* return a pointer to vec_ */

private:
double vec_[3];
};


I want to wrap it with Python so I can do:
a = demo.A(1.,2.,3)
coord = a.get_vec() # coord is a numpy array

I don't want to apply a typemap on all 'double*' returned value, because there
are of course not all 3-length vector.

A first solution would be to change the header file like this:
typedef double* SWIG_DOUBLE_VECTOR3;
typedef const double* SWIG_DOUBLE_VECTOR3_CONST;

class A{
...
SWIG_DOUBLE_VECTOR3 get_vec(void);
SWIG_DOUBLE_VECTOR3_CONST get_vec(void) const;
...
};

and then apply typemap on SWIG_DOUBLE_VECTOR3, SWIG_DOUBLE_VECTOR3_CONST, but it
would be better to not alter the header file.

Another solution is to %extend A with a get_vec_helper function, where the
returned value is now a argument, and apply a typemap on it. Then %ignore
get_vec, and %rename get_vec_helper to get_vec:

%module demo

%{
#define SWIG_FILE_WITH_INIT
#include "a.hpp"
%}

%include "numpy.i"

%init %{
import_array();
%}

%typemap(in,numinputs=0,fragment="NumPy_Fragments")
double *swig_argout_double_pointer_len3 (double* temp) {
temp = new double[3];
$1 = temp;
}

%typemap(argout) double* swig_argout_double_pointer_len3 {
int nd=1; /* a vector is 1 dimension */
npy_intp dims[nd];
dims[0] = 3; /* vector has 3 components */
$result = PyArray_SimpleNewFromData(nd,dims,NPY_DOUBLE,temp$argnum);
if (! $result) SWIG_fail;
}

%ignore A::get_vec;
%rename(get_vec) A::get_vec_helper;

%include "a.hpp"

%extend A {
void get_vec_helper(double *swig_argout_double_pointer_len3)
{
double *vec = $self->get_vec();
swig_argout_double_pointer_len3[0] = vec[0];
swig_argout_double_pointer_len3[1] = vec[1];
swig_argout_double_pointer_len3[2] = vec[2];
};
}


It's work. But it's quite complicated for apparently simple task...

Do you see anyway to make the process simpler?


Best,
David

------------------------------------------------------------------------------
This SF email is sponsosred by:
Try Windows Azure free for 90 days Click Here
http://p.sf.net/sfu/sfd2d-msazure
_______________________________________________
Swig-user mailing list
Swig...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/swig-user

David Froger

unread,
Mar 22, 2012, 5:36:04 AM3/22/12
to swig-user
Excerpts from David Froger's message of jeu. mars 22 10:17:54 +0100 2012:

I just realized that typemaps defined in numpy.i can apply directly on get_vec_helper.
Here it is simpler (it works):

%module demo

%{
#define SWIG_FILE_WITH_INIT
#include "a.hpp"
%}

%include "numpy.i"

%init %{
import_array();
%}

%ignore A::get_vec;
%rename(get_vec) A::get_vec_helper;

%include "a.hpp"

%extend A {
void get_vec_helper(double ARGOUT_ARRAY1[3])
{


double *vec = $self->get_vec();

ARGOUT_ARRAY1[0] = vec[0];
ARGOUT_ARRAY1[1] = vec[1];
ARGOUT_ARRAY1[2] = vec[2];
};

Reply all
Reply to author
Forward
0 new messages