How can I reuse code for swig type templates?

I have two swig type templates with a bunch of duplicate code. I would like to consolidate the code like this:

%{
   #include "structure_defs.h"
%}

%ignore Cartesian2PyList(const schrodinger::Cartesian&);
PyObject* Cartesian2PyList(const schrodinger::Cartesian& cartesian)
{
  PyObject *o;
  o = PyList_New(3);
  PyObject* item = PyFloat_FromDouble(cartesian.x);
  PyList_SetItem(o, 0, item);
  item = PyFloat_FromDouble(cartesian.y);
  PyList_SetItem(o, 1, item);
  item = PyFloat_FromDouble(cartesian.z);
  PyList_SetItem(o, 2, item);
  return o; 
}

%typemap(out) schrodinger::Cartesian
{
  $result = Cartesian2PyList($1);
}
%typemap(out) std::vector<schrodinger::Cartesian>
{
  PyObject *o;
  o = PyList_New($1.size());
  for (uint i=0; i<$1.size(); i++) {
    PyObject *elem = Cartesian2PyList($1.at(i));
    PyList_SetItem(o, i, elem);
  }
  $result = o;
}

%include "cartesian.h"

      

However, this fails to compile because the definition for Cartesian2PyList cannot be found at compile time. What's the best way to reuse code across multiple types?

+3


source to share


1 answer


You can pipe the code directly into the generated .c file with %{ %}

. The easiest way to reuse code inside the shell is to simply place it inside, possibly as a static function, so it doesn't collide with anything else in the same module. In your example, this will work:

%{
   #include "structure_defs.h"
%}

%{
static PyObject* Cartesian2PyList(const schrodinger::Cartesian& cartesian)
{
  PyObject *o;
  o = PyList_New(3);
  PyObject* item = PyFloat_FromDouble(cartesian.x);
  PyList_SetItem(o, 0, item);
  item = PyFloat_FromDouble(cartesian.y);
  PyList_SetItem(o, 1, item);
  item = PyFloat_FromDouble(cartesian.z);
  PyList_SetItem(o, 2, item);
  return o; 
}
%}

%typemap(out) schrodinger::Cartesian
{
  $result = Cartesian2PyList($1);
}
%typemap(out) std::vector<schrodinger::Cartesian>
{
  PyObject *o;
  o = PyList_New($1.size());
  for (uint i=0; i<$1.size(); i++) {
    PyObject *elem = Cartesian2PyList($1.at(i));
    PyList_SetItem(o, i, elem);
  }
  $result = o;
}

%include "cartesian.h"

      

You could combine the two blocks %{ %}

into one block if you like.



I also removed the directive %ignore

there, because the code inside is %{ %}

just being output to the generated module and not wrapped, so it would be redundant. On the other hand, if you really want it to be wrapped as well as defined in the generated code, you can use %inline %{ ... %}

for example:

%inline %{
static PyObject* Cartesian2PyList(const schrodinger::Cartesian& cartesian)
{
    //...
}
%}

      

There are more smart things that you can use if you write a more general SWIG-code, not just one module, see. Fragments , %define

and $typemap

. In the simple case, it is sufficient to simply write the code for use inside the module, as shown above.

+2


source







All Articles