[C++-sig] Problems with def(self_ns::str(self)) and virtual functions
John F Meinel Jr
boost-users at johnmeinel.com
Tue Feb 10 04:13:54 CET 2004
I've been testing out boost::python for wrapping some C++ code that I've
written, but I had some weird results trying to get the "__str__"
functionality to work correctly.
I have a base C++ class that has a virtual function in it (with a
default value). I derive another C++ class from it and change the
virtual function.
I also create a std::ostream << operator so that I can print this class.
Here is the code:
struct Base {
virtual ~Base() {}
virtual int f() const { return 12345; }
};
struct Derived : Base {
virtual int f() const { return 54321; }
};
inline int call_f(Base& b) { return b.f(); }
inline std::ostream& operator<<(std::ostream& os, const Base& b) {
return os << "A: " << b.f() << std::endl;
}
///// Begin Python Wrapper
#include <boost/python.hpp>
using namespace boost::python;
struct BaseWrap : Base {
BaseWrap(PyObject* self_)
: self(self_)
{ }
BaseWrap(PyObject* self_, const Base& b)
: self(self_)
, Base(b)
{ }
int f() const { return call_method<int>(self, "f"); }
int default_f() const { return Base::f(); }
PyObject *self;
};
BOOST_PYTHON_MODULE(test2) {
class_<Base, BaseWrap>("Base")
.def("f", Base::f, BaseWrap::default_f)
.def(self_ns::str(self))
;
class_<Derived, bases<Base> >("Derived")
// Without this, it doesn't work
.def(self_ns::str(self))
;
def("call_f", call_f);
}
///// End Python Wrapper
First, the Tutorial doesn't include the need for BaseWrap to have both
constructors, but it wouldn't compile without both of them (I am using
boost-1.31.0 with MSVC 2003 and python 2.3, though I am trying to get it
all to work with GCC 3.2.2)
First, I can test that without the python wrapper, in a simple C++
script I can do
std::cout << Base() << std::endl;
and
std::cout << Derived() << std::endl;
and I get the correct output. So I know that in C++ the << operator is
calling the appropriate overloaded function.
However, when I load this library in python, if I don't define
.def(self_ns::str(self)) for the Derived class, it prints out the exact
string for the Base().
Here is the exact python code that I type
>>> import test2
>>> import test2
>>> b = test2.Base()
>>> b.f()
12345
>>> test2.call_f(b)
12345
>>> print b
A: 12345
>>> d = test2.Derived()
>>> d.f()
54321
>>> test2.call_f(d)
54321
>>> print d
A: 12345
With __str__ redefined for the Derived class I get
>>> print d
A: 54321
Which is what I want.
What is really weird is that call_f() works correctly in python, even if
I derive a class in python.
>>> class MyClass(test2.Base):
... def f(self):
... return 9876
...
>>> m = MyClass()
>>> m.f()
9876
>>> test2.call_f(m)
9876
>>> print m
A: 12345
Does anyone know why the call_f() operator is using the correct
overload, but the __str__ operator isn't?
Thanks,
John
=:->
More information about the Cplusplus-sig
mailing list