boost/python/wrapper.hpp
はじめに
仮想関数を「Python でオーバーライド」可能なクラス T
をラップするため、つまり C++ から仮想関数を呼び出すときに Python における派生クラスの当該メソッドが呼び出されるよう、これらの仮想関数を Python から呼び出せるようオーバーライドする C++ ラッパクラスをTから派生させて作成しなければならない。このヘッダのクラスを使用して、そういった作業を容易にできる。
クラス
override
クラス
-
class override : object
C++ 仮想関数の Python オーバーライドをカプセル化する。
override
オブジェクトは Python の呼び出し可能オブジェクトかNone
のいずれかを保持する。
override
クラスの概要
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;
};
};
override
クラスのオブザーバ関数
-
template<class ...Args>
unspecified operator()(Args) const - 効果
*this が Python の呼び出し可能オブジェクトを保持している場合、ここに示す方法で指定した引数で呼び出す。それ以外の場合、
error_already_set
を投げる。- 戻り値
Python の呼び出し結果を保持する未規定型のオブジェクト。C++ 型
R
への変換は、結果のオブジェクトのR
への変換により行われる。変換に失敗した場合、error_already_set
を投げる。
wrapper
クラステンプレート
-
class wrapper
ラッパクラスを
T
とwrapper<T>
の両方から派生することで、その派生クラスの記述が容易になる。
wrapper
クラステンプレートの概要
namespace boost
{
class wrapper
{
protected:
override get_override(char const* name) const;
};
};
wrapper
クラステンプレートのオブザーバ関数
例
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/wrapper.hpp>
#include <boost/python/call.hpp>
using namespace boost::python;
// 純粋仮想関数を 1 つ持つクラス
struct P
{
virtual ~P(){}
virtual char const* f() = 0;
char const* g() { return "P::g()"; }
};
struct PCallback : P, wrapper<P>
{
char const* f()
{
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // vc6/vc7 のための workaround
return call<char const*>(this->get_override("f").ptr());
#else
return this->get_override("f")();
#endif
}
};
// 非純粋仮想関数を 1 つ持つクラス
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"))
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // vc6/vc7 のための workaround
return call<char const*>(f.ptr());
#else
return f();
#endif
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)
;
}