...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
To wrap a class T such that its virtual functions can be "overridden
in Python"—so that the corresponding method of a Python derived
class will be called when the virtual function is invoked from C++—you
must create a C++ wrapper class derived from T
that overrides those virtual functions so that they call into Python. This
header contains classes that can be used to make that job easier.
Encapsulates a Python override of a C++ virtual function. An override object
either holds a callable Python object or None
.
namespace boost { class override : object { public: unspecified operator() const; template <class A0> unspecified operator(A0) const; template <class A0, class A1> unspecified operator(A0, A1) const; ... template <class A0, class A1, ...class An> unspecified operator(A0, A1, ...An) const; }; };
unspecified operator() const; template <class A0> unspecified operator(A0) const; template <class A0, class A1> unspecified operator(A0, A1) const; ... template <class A0, class A1, ...class An> unspecified operator(A0, A1, ...An) const;
If *this holds a callable Python object, it is invoked with the specified arguments in the manner specified here. Otherwise, throws error_already_set.
An object of unspecified type that holds the Python result of the invocation and, when converted to a C++ type R, attempts to convert that result object to R. If that conversion fails, throws error_already_set.
Deriving your wrapper class from both T
and wrapper<T>
makes writing that derived class easier.
namespace boost { class wrapper { protected: override get_override(char const* name) const; }; };
override get_override(char const* name) const;
name is a ntbs.
If *this
is the C++ base class subobject of a Python derived class instance
that overrides the named function, returns an override object that
delegates to the Python override. Otherwise, returns an override
object that holds None
.
#include <boost/python/module.hpp> #include <boost/python/class.hpp> #include <boost/python/wrapper.hpp> #include <boost/python/call.hpp> using namespace boost::python; // Class with one pure virtual function struct P { virtual ~P(){} virtual char const* f() = 0; char const* g() { return "P::g()"; } }; struct PCallback : P, wrapper<P> { char const* f() { return this->get_override("f")(); } }; // Class with one non-pure virtual function struct A { virtual ~A(){} virtual char const* f() { return "A::f()"; } }; struct ACallback : A, wrapper<A> { char const* f() { if (override f = this->get_override("f")) return f(); return A::f(); } char const* default_f() { return this->A::f(); } }; BOOST_PYTHON_MODULE_INIT(polymorphism) { class_<PCallback,boost::noncopyable>("P") .def("f", pure_virtual(&P::f)) ; class_<ACallback,boost::noncopyable>("A") .def("f", &A::f, &ACallback::default_f) ; }