[C++-sig] How to wrap reference to abstract base class to get C++ polymorphism

Kun Hong kun.hong at uqconnect.edu.au
Tue May 25 09:34:08 CEST 2010


On 20/05/2010, at 11:03 PM, Kun Hong wrote:

> Hi,
>
> I have a maybe entry-level question. But it really troubled me for a
> while.
>
> I need to wrap a C++ library which has some factory method to return
> references to some abstract base classes. So the implementation is
> hidden. If I want a python equivalent to the abstract base class
> reference type
> (so the polymorphism can work), how should I do it?
>
> Please see a very simplified example below which demonstrates what I
> mean.
>

Finally, I get to understand it and be able to answer my own question.
Post my own answer so future reader can get a pointer directly.

The answer is in the test code that comes with boost python library.
The code is in libs/python/test/polymorphism.{cpp,py}

I got my code working like below:

========== test.cpp ==========


#include <boost/python.hpp>

using namespace boost::python;


class B
{
public:
     virtual const char *getName() const = 0;

     virtual int getValue() const
     {
         return 10;
     }
};

class C : public B
{
public:
     virtual const char *getName() const
     {
         return "Class C";
     }

};

struct BWrap : public B
{
     BWrap(PyObject *self) : mSelf(self) {}
     PyObject *mSelf;

     const char *getName() const
     {
         return call_method<const char *>(mSelf, "getName");
     }
};

const B &getB()
{
     static boost::shared_ptr<B> b(new C);

     return (*b.get());
}


BOOST_PYTHON_MODULE(Test)
{

     class_<B, BWrap, boost::noncopyable> ("B", no_init)
         .def("getName", pure_virtual(&B::getName))
         .def("getValue", &B::getValue)
     ;

     class_<C, bases<B> >("C")
         .def("getName", &C::getName)
     ;

     def("getB", &getB,  
return_value_policy<reference_existing_object>());
}

======== test.py =========
from Test import *

print getB().getName()
print getB().getValue()
c = C()
print c.getName()
print c.getValue()
#b = B()
#print b.getName()
#print b.getValue()

=== end

Not fully understand the pure_virtual call though, which doesn't  
prevent B
instance be created in python. "no_init" is needed for preventing B  
creation.

But, fun learning boost python, a lot to learn.

Kun


More information about the Cplusplus-sig mailing list