#!/usr/bin/env python # coding: utf-8 # ## Inheriting C++ classes from Python # 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` # In[1]: import ROOT # 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. # In[2]: get_ipython().run_cell_magic('cpp', '-d', '#include "TObject.h"\n#include "Python.h"\n#include \nvoid call_python_method(PyObject* self, const char* method)\n{\n // check arguments\n if ( 0 == self || 0 == method ) { throw std::runtime_error("Invalid Python object and method"); }\n // call Python\n PyObject* r = PyObject_CallMethod(self, const_cast(method), const_cast(""));\n if ( 0 == r ) { PyErr_Print(); return;}\n // release used objects\n Py_XDECREF( r ) ;\n //\n return;\n}\n\nclass Base {\n public:\n Base() {}\n virtual ~Base() {}\n virtual void Foo() { cout << "base::Foo" << endl; }\n void CallFoo() { this->Foo(); }\n};\n\nclass PyBase : public Base {\n public:\n PyBase(PyObject* self) : fSelf(self) {}\n virtual ~PyBase() {}\n virtual void Foo() { call_python_method(fSelf,"Foo"); }\n private:\n PyObject* fSelf;\n};\n') # Now we define the python `PyDerived` class that inherits from the just declared C++ `PyBase` # In[3]: 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. # In[4]: d = PyDerived() d.CallFoo() o = ROOT.Base() o.CallFoo() # If we put the objects in a `std::vector` we can exercise true polymorphic access from the C++ side # In[5]: v = ROOT.vector('Base*')() v.push_back(d) v.push_back(o) for i in v : i.Foo()