3
votes

We are trying to use SWIG to wrap a C++ template library for different languages (Python, Java, R..). We do not want to use a different class name in the traget language for every type instantiation. Instead, we'd like to get a single dispatching class (just like SWIG handles overloaded functions). As we have many classes, we also want to let SWIG extract the classes and methods from given C++ headers.

Example: Assume a c++ header (read-only) containing

template< typename T >
class Foo {
    Foo(const T * t);
    const T* getVal() const;
    void setVal(const T* t);
};

Now we'd like to write an interface file for SWIG which creates a single class which dispatches to the right template instantiation (it'd be ok if this happened in every function call). In Python we'd like to allow something like this

from foo import Foo
v_int = Foo(1)
v_int.setVal(v_int.getVal())
v_str = Foo("string")
v_str.setVal(v_str.getVal())

I have some idea how to do this manually, but it would basically mean I have to write my own wrapping class in C++ with every member function in it that the template class defines. With the large number of classes we want to wrap this becomes an unpractical solution.

Any idea? E.g. is there a way to "iterate" through all member functions in a SWIG interface file?

1

1 Answers

0
votes

I haven't tested this myself but the SWIG documentation on C++ template seems to suggest this is fairly easy, you just have to tell SWIG which classes you want the template to accept. Adapting the example there to your example header, your SWIG file would look something like:

%module foo
%{
#include "foo.h"
%}

template< typename T>
class Foo {
    Foo(const T *t);
    const T* getVal() const;
    void setVal(const T* t);
};

%template(i) foo<int>;
%template(str) foo<string>;

plus similar lines for any further types you want to use with the template.

You'd then use it in python like:

>>> v_int = Foo.i(1)
>>> v_int.setVal(v_int.getVal())
>>> v_str = Foo.str("string")
>>> v_str.setVal(v_str.getVal())

Now, I know you said you don't want to use a different class name for every instantiation, and since here you have to decide the type of object at the time you create it's not the perfectly transparent template usage that you get in native C++. But it seems to be reasonably close, and far less work than writing wrapper classes for everything.