[C++-sig] call_back and inheritance

J. Michael Owen mikeowen at llnl.gov
Fri Aug 2 22:36:10 CEST 2002


Whoops, looks like the tar archive I used for the example files in my post
didn't travel very well.  Here's the ascii version.

Mike.

------------------------------ C++ source --------------------------------------

#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),
//     mSelf(self) {}

// private:
//   PyObject* mSelf;
// };

//------------------------------------------------------------------------------
// 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("pureVirtualMethod", &AbstractBase::pureVirtualMethod)
          .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()
            );
}

//------------------------------------------------------------------------------
// The BPL wrapped python module.
//------------------------------------------------------------------------------
BOOST_PYTHON_MODULE_INIT(callback) {

  try {
    module mod("callback");

    // AbstractBase
    wrapAbstractBase(mod);

    // Derived
    wrapDerived(mod);

  } catch(...) {
    handle_exception();
  }

}

--------------------------------- python example -------------------------------

import callback

class overrideAbstract(callback.AbstractBase):
    def __init__(self):
        callback.AbstractBase.__init__(self)
        return

    def pureVirtualMethod(self):
        print "This is python!  overrideAbstact.pureVirtualMethod()"
        return

    def processValue(self):
        print "This is python!  overrideAbstact.processValue()"
        return 10

class overrideDerived(callback.Derived):
    def __init__(self):
        callback.Derived.__init__(self)
        return

    def pureVirtualMethod(self):
        print "This is python!  overrideDerived.pureVirtualMethod()"
        callback.Derived.pureVirtualMethod(self)
        return

a = callback.Derived()
b = overrideAbstract()
c = overrideDerived()

print "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
print type(a)
print a.callVirtualMethod()
print "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
print type(b)
print b.callVirtualMethod()
print "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
print type(c)
print c.callVirtualMethod()
print "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"

-- 
 "Hey...where are the sunflower seeds?" |       J. Michael Owen         
        o_o /                           |       Phone:  925-423-7160     
        (")                             |       Email:  mikeowen at llnl.gov
       \/'\/                            |
____(__(,_,)_______________________________________________________________




More information about the Cplusplus-sig mailing list