[C++-sig] call_back and inheritance
David Abrahams
dave at boost-consulting.com
Sat Aug 3 14:12:03 CEST 2002
From: "Mike Owen" <mikeowen at speakeasy.net>
> Ah, I see what you're saying, and indeed when I remove the .def() from
the
> AbstractBase definitions I can correctly override and use the
AbstractBase
> from python. Cool!
>
> However, I still don't see how I can get the ability to override the
method
> again in python classes that inherit from the Derived C++ class.
> I seem to
> be having trouble trying to define a call_back class for the Derived
class in
> this example, and therefore I have not been able to get a python method
to
> override it's methods. How should we handle the wrapping of Derived so
we
> can override it's methods too?
Mike,
Rule #1 of support requests: provide a precise description of what you did,
what results you got, and what results you expected.
I don't see anything here that prevents you from overriding the
"pureVirtualMethod" of Python classes derived from Derived.
OK, looking more closely, I spy this line:
.def("pureVirtualMethod", &AbstractBase::pureVirtualMethod)
virtual functions should basically never be exposed directly with .def().
If you want to expose the default implementation of a virtual function you
need to write a thin non-virtual wrapper over it, much as described in the
v1 docs (www.boost.org/libs/python/doc/overriding.html). The virtual
function overriding procedure has remained largely unchanged from v1.
HTH2,
Dave
> Thanks for the pointers!
>
> Mike.
>
> Here's the modified version of the previous example where I've removed
the
> .def for the pure virtual method from AbstractBase call_back again.
> #include <iostream>
> using namespace std;
>
> // BPL includes.
> #include "boost/python/class.hpp"
> #include "boost/python/module.hpp"
> #include "boost/python/call_method.hpp"
> using namespace boost::python;
>
>
//-------------------------------------------------------------------------
-----
> // Class definitions.
>
//-------------------------------------------------------------------------
-----
> class AbstractBase {
> public:
> AbstractBase():
> mInternalValue(-10) {}
> virtual ~AbstractBase() {}
> virtual void pureVirtualMethod() = 0;
> virtual int processValue() = 0;
>
> void printInternalValue() {
> cout << "AbstractBase::InternalValue = " << mInternalValue << endl;
> }
>
> void callVirtualMethod() {
> cout << "AbstractBase::callVirtualMethod()" << endl;
> pureVirtualMethod();
> }
>
> int internalValue() {
> return mInternalValue;
> }
>
> private:
> int mInternalValue;
> };
>
> class Derived: public AbstractBase {
> public:
> Derived():
> AbstractBase() {}
> virtual ~Derived() {}
>
> virtual void pureVirtualMethod() {
> cout << "Derived::pureVirtualMethod()" << endl;
> printInternalValue();
> }
>
> virtual int processValue() {
> cout << "Derived::processValue()" << endl;
> return 2*internalValue();
> }
>
> };
>
>
//-------------------------------------------------------------------------
-----
> // Call back class to provide BPL overrides for AbstractBase.
>
//-------------------------------------------------------------------------
-----
> class AbstractBaseCallBack: public AbstractBase {
> public:
> AbstractBaseCallBack(PyObject *self):
> AbstractBase(),
> mSelf(self) {}
>
> void pureVirtualMethod() {
> return call_method<void>(mSelf, "pureVirtualMethod");
> }
>
> int processValue() {
> return call_method<int>(mSelf, "processValue");
> }
>
> private:
> PyObject* mSelf;
> };
>
>
//-------------------------------------------------------------------------
-----
> // Call back class to provide BPL overrides for Derived.
>
//-------------------------------------------------------------------------
-----
> class DerivedCallBack: public Derived {
> public:
> DerivedCallBack(PyObject *self):
> Derived(),
> mSelf(self) {}
>
> void pureVirtualMethod() {
> return call_method<void>(mSelf, "pureVirtualMethod");
> }
>
> int processValue() {
> return call_method<int>(mSelf, "processValue");
> }
>
> private:
> PyObject* mSelf;
> };
>
> // class DerivedCallBack: public Derived,
> // public AbstractBaseCallBack {
> // public:
> // DerivedCallBack(PyObject *self):
> // Derived(),
> // AbstractBaseCallBack(self) {}
> // };
>
>
//-------------------------------------------------------------------------
-----
> // Helper methods to wrap the classes in this module.
>
//-------------------------------------------------------------------------
-----
> void wrapAbstractBase(module& mod) {
> mod.add(class_<AbstractBase,
> boost::shared_ptr<AbstractBaseCallBack>,
> boost::noncopyable>("AbstractBase")
> .def_init()
> .def("printInternalValue", &AbstractBase::printInternalValue)
> .def("callVirtualMethod", &AbstractBase::callVirtualMethod)
> );
> }
>
> void wrapDerived(module& mod) {
> mod.add(class_<Derived,
> bases<AbstractBase>,
> boost::shared_ptr<DerivedCallBack>,
> boost::noncopyable>("Derived")
> .def_init()
> .def("pureVirtualMethod", &AbstractBase::pureVirtualMethod)
> );
> }
>
>
//-------------------------------------------------------------------------
-----
> // The BPL wrapped python module.
>
//-------------------------------------------------------------------------
-----
> BOOST_PYTHON_MODULE_INIT(callback) {
> module mod("callback");
>
> // AbstractBase
> wrapAbstractBase(mod);
>
> // Derived
> wrapDerived(mod);
>
> }
More information about the Cplusplus-sig
mailing list