Swig: class template extension to provide __str__

Say you have a template class Fooand you want to wrap it transparently in Swig so you can print the class:

>>> from example import *
>>> f = Foo2()
>>> print(f)
In Foo class!

I followed this post and this one . Therefore my header file:

#include <iostream>

template <int d> class Foo {

public:

  friend std::ostream &operator<<(std::ostream &os, const Foo &m) {
    os << "Inside Foo class!" << std::endl;
    return os;
  }
};

And my interface file:

%{
#include <sstream>
#include <iostream>
#include "foo.hpp"
%}

%include "std_iostream.i"

// Try grabbing it unmodified
%include "foo.hpp"


/* Instantiate a few different versions of the template */
%template(Foo2) Foo<2>;
%template(Foo3) Foo<3>;


%extend Foo<2> {

  const char *__str__() {

    std::ostringstream oss(std::ostringstream::out);
    oss << *self;
    return oss.str().c_str();
  }
};

So this works fine, I can still print the object, but I would like to generalize it to any value of the template parameter, since there is no point in copying this code for each template parameter. I tried the following in the interface file, but this did not work:

template <int d> class Foo {

public:

  %extend {
    const char *__str__() {

      std::ostringstream oss(std::ostringstream::out);
      oss << *self;
      return oss.str().c_str();
    }
  }
};
+4
source share
2 answers

%extend , , :

%extend Foo {
  const char *__str__() {
    std::ostringstream oss(std::ostringstream::out);
    oss << *self;
    return oss.str().c_str();
  }
};

%template(Foo2) Foo<2>;
%template(Foo3) Foo<3>;

SWIG :

%define WRAP_FOO(N)

  %template( Foo ## N ) Foo<N>;

  %extend Foo<N> {
    const char *__str__() {
      std::ostringstream oss(std::ostringstream::out);
      oss << *self;
      return oss.str().c_str();
    }
  };

%enddef

/* Instantiate a few different versions of the template */
WRAP_FOO(2)
WRAP_FOO(3)

, undefined, .c_str() std::string, .

+3

%extend, , , , OpenStudio

, , 2 , %import .i . - , SWIG.

, , %include "foo.hpp" , . .i - :

%{
#include <sstream>
#include <iostream>
#include "foo.hpp"
%}

%include "std_iostream.i"

// Don't let SWIG directly parse foo.hpp
// %include "foo.hpp"



template <int d> class Foo {

public:
  // include here prototypes for all functions
  // you want exposed. You don't need the implementation like in 
  // a normal C++ template declaration

  // include here any extensions you want to add
  %extend {
    const char *__str__() {

      std::ostringstream oss(std::ostringstream::out);
      oss << *self;
      return oss.str().c_str();
    }
  }
};

/* Instantiate a few different versions of the template */
%template(Foo2) Foo<2>;
%template(Foo3) Foo<3>;

SWIG hpp API:

.i :

%{
#include <sstream>
#include <iostream>
#include "foo.hpp"
%}

%include "std_iostream.i"

// let swig directly parse foo.hpp
%include "foo.hpp"


/* Instantiate a few different versions of the template */
%template(Foo2) Foo<2>;
%template(Foo3) Foo<3>;

.hpp:

#include <iostream>

template <int d> class Foo {

public:
#ifdef SWIG
  %extend {
    const char *__str__() {

      std::ostringstream oss(std::ostringstream::out);
      oss << *self;
      return oss.str().c_str();
    }
  }
#endif

  friend std::ostream &operator<<(std::ostream &os, const Foo &m) {
    os << "Inside Foo class!" << std::endl;
    return os;
  }
};
+1

All Articles