#806 implementing C++ virtual functions trough %extend mechanism

open
Marcelo Matus
python (259)
5
2012-12-21
2007-03-29
No

Am trying to wrap some C++ code for Python using latest version of SWIG. There exist some base/derived classes in C++ code, and I'd like to add some virtual functions to these (for some reasons, these should be added in interface file, if possible, and not in C++ code directly); but it seems that it isn't possible. Here is small example demonstrating the problem:

My C++ files are as follows:

/********** foo.h **********/

#ifndef FOO_H
#define FOO_H

#include <vector>

class Base
{
public:
virtual ~Base(void) {}
};

class Derived1 : public Base
{
public:
~Derived1(void) {}
};

class Derived2 : public Base
{
public:
~Derived2(void) {}
};

class Foo
{
public:
Foo(void);
~Foo(void);

const std::vector<Base*> &getItems(void) const { return items_; }

private:
std::vector<Base*> items_;
};

#endif

/********** foo.cpp **********/

#include "foo.h"

Foo::Foo(void)
{
items_.push_back(new Derived1());
items_.push_back(new Derived1());
items_.push_back(new Derived2());
}

Foo::~Foo(void)
{
for (std::vector<Base*>::iterator it = items_.begin();
it != items_.end(); ++it)
delete *it;
}

My SWIG interface file is as follows:

/********** foo.i **********/

%module Foo

%{
#include "foo.h"
%}

%include std_vector.i

%template(VectorOfBases) std::vector<Base *>;

%include "foo.h"

%extend Base {
virtual const char *__str__() const
{
return "I'm Base class";
}
}

%extend Derived1 {
const char *__str__() const
{
return "I'm Derived1 class";
}
}

%extend Derived2 {
const char *__str__() const
{
return "I'm Derived2 class";
}
}

I'm compiling above using following sequence of commands (on Linux):
swig -python -c++ foo.i
g++ -fpic -c -Wall foo.cpp
g++ -fpic -c -Wall -I/usr/include/python2.4 foo_wrap.cxx
g++ -shared foo.o foo_wrap.o -o _Foo.so

Python code using SWIG generated module is as follows:

#! /usr/bin/python

import Foo

foo = Foo.Foo()
for item in foo.getItems():
print item

I'd like this code to print:
I'm Derived1 class
I'm Derived1 class
I'm Derived2 class
but it's printing:
I'm Base class
I'm Base class
I'm Base class
instead.

Discussion