[C++-sig] Doubts with wrapping/using abstract bases.
Prabhu Ramachandran
prabhu at aero.iitm.ernet.in
Sun Aug 10 20:57:02 CEST 2003
Hi,
I think I have a fairly serious misunderstanding of how Boost.Python
wraps abstract virtual classes. I'd appreciate any clarifications.
Here is a simple example:
// ---------------- holder.hpp ----------------------
#include <vector>
#include <iostream>
struct A {
virtual ~A() {}
virtual void f()=0;
};
struct B: A {
void f() {std::cout << "B::f\n";}
};
struct Holder {
Holder() {}
void add(A* a) {arr.push_back(a);}
A* get(const std::size_t n) {return arr[n];}
private:
std::vector<A*> arr;
};
void func(A* a) {a->f();}
// --------------------------------------------------
I wrap this with Pyste (CVS) and get wrapper code that looks like so
(edited for brevity):
// --------------------------------------------------
#include <boost/python.hpp>
#include <holder.hpp>
using namespace boost::python;
struct A_Wrapper: A
{
A_Wrapper(PyObject* self_, const A& p0): A(p0), self(self_) {}
A_Wrapper(PyObject* self_): A(), self(self_) {}
void f() {call_method< void >(self, "f");}
PyObject* self;
};
struct B_Wrapper: B
{
B_Wrapper(PyObject* self_, const B& p0): B(p0), self(self_) {}
B_Wrapper(PyObject* self_): B(), self(self_) {}
void f() {call_method< void >(self, "f");}
void default_f() {B::f();}
PyObject* self;
};
void add_wrapper(Holder* c, std::auto_ptr< B_Wrapper > o)
{c->add(o.get()); o.release();}
BOOST_PYTHON_MODULE(holder)
{
class_< A, boost::noncopyable, std::auto_ptr< A_Wrapper > >
("A", init< >());
class_< B, bases< A > , std::auto_ptr< B_Wrapper > >("B", init< >())
.def(init< const B& >())
.def("f", &B::f, (void (B_Wrapper::*)())&B_Wrapper::default_f);
class_< Holder >("Holder", init< >())
.def(init< const Holder& >())
.def("add", &add_wrapper)
.def("get", &Holder::get, return_internal_reference< 1 >());
def("func", &func);
}
// --------------------------------------------------
This looks good to me. Now I try the following from Python:
>>> import holder
>>> b = holder.B()
>>> b.f()
B::f
>>> holder.func(b)
B::f
>>> # Everything is OK.
>>> h = holder.Holder ()
>>> h.add(b)
>>> b1 = h.get(0)
>>> b1.f()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'A' object has no attribute 'f'
I did not expect this since this is perfectly legal in C++,
i.e. b1->f() in C++ is legal and used commonly. So what am I doing
wrong?
Thanks!
cheers,
prabhu
More information about the Cplusplus-sig
mailing list