In this exercise we would like to demostrate the inheritance of a C++ class from Python. The base class in C++ is Base
and we want to have an specialization of if in Python PyDerived
import ROOT
Welcome to ROOTaaS 6.05/01
To bridge between the C++ and Python virtual functions we need to define a proper C++ class that will forward the virtual function calls to the the Python object. The only trick here is that this C++ class needs to have a constructor to receive the self
from the Python object for use afterwords.
The implemetation is done completely in C++ with the next block.
%%cpp -d
#include "TObject.h"
#include "Python.h"
#include <stdexcept>
void call_python_method(PyObject* self, const char* method)
{
// check arguments
if ( 0 == self || 0 == method ) { throw std::runtime_error("Invalid Python object and method"); }
// call Python
PyObject* r = PyObject_CallMethod(self, const_cast<char*>(method), const_cast<char*>(""));
if ( 0 == r ) { PyErr_Print(); return;}
// release used objects
Py_XDECREF( r ) ;
//
return;
}
class Base {
public:
Base() {}
virtual ~Base() {}
virtual void Foo() { cout << "base::Foo" << endl; }
void CallFoo() { this->Foo(); }
};
class PyBase : public Base {
public:
PyBase(PyObject* self) : fSelf(self) {}
virtual ~PyBase() {}
virtual void Foo() { call_python_method(fSelf,"Foo"); }
private:
PyObject* fSelf;
};
True
Now we define the python PyDerived
class that inherits from the just declared C++ PyBase
class PyDerived(ROOT.PyBase):
def __init__(self): ROOT.PyBase.__init__(self, self)
def Foo(self): print 'Python::Foo'
Now that we have the two classes defined (Base
and PyDerived
) we exercise calling the Foo
method.
d = PyDerived()
d.CallFoo()
o = ROOT.Base()
o.CallFoo()
Python::Foo base::Foo
If we put the objects in a std::vector<Base*>
we can exercise true polymorphic access from the C++ side
v = ROOT.vector('Base*')()
v.push_back(d)
v.push_back(o)
for i in v : i.Foo()
Python::Foo base::Foo