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

ラッパクラスを Twrapper<T> の両方から派生することで、その派生クラスの記述が容易になる。

wrapper クラステンプレートの概要

namespace boost
{
  class wrapper
  {
   protected:
      override get_override(char const* name) const;
  };
};

wrapper クラステンプレートのオブザーバ関数

override get_override(char const *name) const
要件

namentbs

戻り値

Python 派生クラスインスタンスが名前 name の関数をオーバーライドしているとして、*this がその C++ 基底クラスのサブオブジェクトである場合、Python のオーバーライドに委譲する override オブジェクトを返す。それ以外の場合、None を保持する override オブジェクトを返す。

#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)
        ;
}