1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
[section boost/python/wrapper.hpp]
[section Introduction]
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.
[endsect]
[section Class `override`]
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;
};
};
``
[endsect]
[section Class `override` observer functions]
``
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;
``
[variablelist
[[Effects][If *this holds a callable Python object, it is invoked with the specified arguments in the manner specified here. Otherwise, throws [link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set].]]
[[Returns][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 [link high_level_components.boost_python_errors_hpp.class_error_already_set error_already_set].]]
]
[endsect]
[section Class template `wrapper`]
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;
};
};
``
[endsect]
[section Class template `wrapper` observer functions]
``override get_override(char const* name) const;``
[variablelist
[[Requires][name is a [link ntbs].]]
[[Returns][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`.]]
]
[endsect]
[section Example]
``
#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)
;
}
``
[endsect]
[endsect]
|