boost/python/call_method.hpp

はじめに

<boost/python/call_method.hpp> は、C++ から Python の呼び出し可能属性を起動する call_method 関数テンプレート多重定義群を定義する。

関数

call_method

template<class R, class ...Args>
R call_method(PyObject *self, char const *method, Args const&)
要件

R はポインタ型、参照型、またはアクセス可能なコピーコンストラクタを持つ完全型。

効果

Python 内で self.method(a1, a2, ...an) を起動する。a1ancall_method に対する引数で、Python のオブジェクトに変換したもの。完全なセマンティクスの説明については、このページを見よ。

戻り値

Python の呼び出し結果を C++ の型 R に変換したもの。

根拠

下の例で見るように、Python でオーバーライド可能な C++ 仮想関数を実装するのに重要である。

以下の C++ コードは、call_method を使用して Python でオーバーライド可能な仮想関数を持つクラスをラップする方法を示している。

C++ のモジュール定義
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/def.hpp>
#include <boost/utility.hpp>
#include <cstring>

// ラップするクラス
class Base
{
 public:
   virtual char const* class_name() const { return "Base"; }
   virtual ~Base() {};
};

bool is_base(Base* b)
{
   return !std::strcmp(b->class_name(), "Base");
}

// ここからラッパコード
using namespace boost::python;

// コールバッククラス
class Base_callback : public Base
{
 public:
   Base_callback(PyObject* self) : m_self(self) {}

   char const* class_name() const { return call_method<char const*>(m_self, "class_name"); }
   char const* Base_name() const { return Base::class_name(); }
 private:
   PyObject* const m_self;
};

using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
    def("is_base", is_base);

    class_<Base,Base_callback, boost::noncopyable>("Base")
        .def("class_name", &Base_callback::Base_name)
        ;

}
Python のコード
>>> from my_module import *
>>> class Derived(Base):
...    def __init__(self):
...       Base.__init__(self)
...    def class_name(self):
...       return self.__class__.__name__
...
>>> is_base(Base()) # C++ から class_name() メソッドを呼び出す
1
>>> is_base(Derived())
0