boost/python/class.hpp
はじめに
<boost/python/class.hpp>
は、ユーザが C++ クラスを Python へエクスポートするためのインターフェイスを定義する。class_
クラステンプレートを宣言し、その引数はエクスポートするクラス型である。また init
、optional
および bases
ユーティリティクラステンプレートもエクスポートし、これらは class_
クラステンプレートと組み合わせて使用する。
<boost/python/class_fwd.hpp>
には class_
クラステンプレートの先行宣言がある。
クラス
class_<T, Bases, HeldType, NonCopyable>
クラステンプレート
-
template<class T, class Bases = bases<>, class HeldType = T, class NonCopyable = unspecified>
class class_ : public object 第 1 引数として渡した C++ 型に対応する Python クラスを作成する。引数は 4 つあるが、必須なのは 1 番目だけである。3 つの省略可能な引数はどのような順序でもよく、Boost.Python は引数の型から役割を判断する。
- テンプレートパラメータ
Bases --
ラップした
T
インスタンスからその直接的または間接的な基本型それぞれへのfrom_python
変換を登録する。多態的な各基底型B
について、間接的に保持されたラップしたB
インスタンスからT
への変換を登録する。HeldType --
T
のコンストラクタを呼び出したとき、またはT
やT*
をptr
、ref
、あるいはreturn_internal_reference
等の CallPolicies を使用せずに Python へ変換したとき、T
のインスタンスをラップする Python オブジェクトへ実際に組み込む型を指定する。詳細は後述する。- 要件
T
、T
の派生クラス、またはpointee
<HeldType>::type
がT
かT
の派生クラスである Dereferenceable 型。- 既定
T
NonCopyable --
T
のインスタンスをコピーするto_python
変換の自動的な登録を抑止する。T
が公開アクセス可能なコピーコンストラクタを持たない場合に必要である。- 要件
与えられた場合、boost::noncopyable でなければならない。
- 既定
boost::noncopyable
以外の未規定の型。
HeldType のセマンティクス
HeldType
がT
から派生している場合、そのエクスポートしたコンストラクタは、HeldType
インスタンスを持つ Python オブジェクトを逆向きに参照するPyObject*
を第 1 引数に受け取らなければならない(例)。この引数は def(init_expr) に渡されるinit-expression
には含まれず、T
の Python インスタンスが作成されるときユーザが明示的に渡すこともない。このイディオムにより、Python 側でオーバーライドする C++ 仮想関数が Python オブジェクトにアクセス可能となり、Python のメソッドが呼び出し可能となる。Boost.Python はHeldType
引数を要求するラップした C++ 関数にT
のラップしたインスタンスを渡すための変換器を自動的に登録する。Boost.Python は
T
のラップしたインスタンスがHeldType
型の引数として渡すことを認めているため、HeldType
のスマートポインタを指定することでユーザはT
へのスマートポインタを受け取るところに Python のT
インスタンスを渡すことができる。std::auto_ptr
や boost::shared_ptr<> といった対象の型を指す入れ子のelement_type
型を持つスマートポインタは自動的にサポートされる。2pointee<HeldType>
を特殊化することで、他のスマートポインタ型もサポートされる。上の 1. で述べたとおり、
HeldType
がT
の派生型に対するスマートポインタの場合、HeldType
のエクスポートしたコンストラクタすべてでPyObject*
を第 1 引数として与えなければならない。上記 1. および 3. 以外でユーザは
has_back_reference<>
を特殊化することで、T
自身が第 1 引数であるPyObject*
で初期化されることをオプション的に指定できる。
class_
クラステンプレートの概要
namespace boost { namespace python
{
template <class T
, class Bases = bases<>
, class HeldType = T
, class NonCopyable = unspecified
>
class class_ : public object
{
// 既定の __init__ を使用するコンストラクタ
class_(char const* name);
class_(char const* name, char const* docstring);
// 既定でない __init__ を指定するコンストラクタ
template <class Init>
class_(char const* name, Init);
template <class Init>
class_(char const* name, char const* docstring, Init);
// 追加の __init__ 関数のエクスポート
template <class Init>
class_& def(Init);
// メソッドの定義
template <class F>
class_& def(char const* name, F f);
template <class Fn, class A1>
class_& def(char const* name, Fn fn, A1 const&);
template <class Fn, class A1, class A2>
class_& def(char const* name, Fn fn, A1 const&, A2 const&);
template <class Fn, class A1, class A2, class A3>
class_& def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
// メソッドを static として宣言
class_& staticmethod(char const* name);
// 演算子のエクスポート
template <unspecified>
class_& def(detail::operator_<unspecified>);
// 生の属性の変更
template <class U>
class_& setattr(char const* name, U const&);
// データメンバのエクスポート
template <class D>
class_& def_readonly(char const* name, D T::*pm);
template <class D>
class_& def_readwrite(char const* name, D T::*pm);
// static データメンバのエクスポート
template <class D>
class_& def_readonly(char const* name, D const& d);
template <class D>
class_& def_readwrite(char const* name, D& d);
// プロパティの作成
template <class Get>
void add_property(char const* name, Get const& fget, char const* doc=0);
template <class Get, class Set>
void add_property(
char const* name, Get const& fget, Set const& fset, char const* doc=0);
template <class Get>
void add_static_property(char const* name, Get const& fget);
template <class Get, class Set>
void add_static_property(char const* name, Get const& fget, Set const& fset);
// pickle のサポート
template <typename PickleSuite>
self& def_pickle(PickleSuite const&);
self& enable_pickling();
};
}}
class_
クラステンプレートのコンストラクタ
-
class_(char const *name)
-
class_(char const *mame, char const *docstring)
-
template<class Init>
class_(char const *name, Init init_spec) -
template<class Init>
class_(char const *name, char const *docstring, Init init_spec) - 要件
name
は Python の識別子の名前付け規約にしたがった ntbs。docstring
が与えられた場合は ntbs でなければならない。init_spec
が与えられた場合、特殊な列挙定数no_init
かT
と互換性のあるinit-expression
のいずれかでなければならない。- 効果
名前
name
の Boost.Python 拡張クラスを保持するclass_
オブジェクトを構築する。現在のスコープにおいて属性name
を新しい拡張クラスに束縛する。- 根拠
必要な
T
インスタンスを作成する__init__
関数をエクスポートせずにラップしたメンバ関数を呼び出すことによって発生する、よくある実行時エラーを避けられるよう、class_<>
コンストラクタ内でコンストラクタ引数を指定できる。
クラステンプレート class_
の変更関数
-
template<class Init>
class_ &def(Init init_expr) - 要件
init_expr
はT
と互換性のあるinit-expression
の結果。- 効果
Init
の合法な接頭辞P
それぞれについて、P
を引数として受け取る拡張クラスに__init__(...)
関数の多重定義を追加する。生成された各多重定義は、上述のセマンティクスに従ってinit_expr
の呼び出しポリシーのコピーを使用してHeldType
のオブジェクトを構築する。Init
の合法な接頭辞の最長のものがM
個の型を有しておりinit_expr
がM
個のキーワードを保持しているとすると、各多重定義の先頭のN
-M
個の引数に使用される。- 戻り値
*this
- 根拠
ユーザはクラスのコンストラクタを容易に Python へエクスポートできる。
-
template<class F>
def(char const *name, Fn fn) -
template<class Fn, class A1>
def(char const *name, Fn fn, A1 const &a1) -
template<class Fn, class A1, class A2>
def(char const *name, Fn fn, A1 const &a1, A2 const &a2) -
template<class Fn, class A1, class A2, class A3>
def(char const *name, Fn fn, A1 const &a1, A2 const &a2, A3 const &a3) - 要件
name
が Python の識別子の名前付け規約にしたがった ntbs。a1
がoverload-dispatch-expression
の結果である場合、有効なのは 2 番目の形式のみでありfn
は引数長がA1
の最大引数長と同じである関数かメンバ関数へのポインタでなければならない。
- 効果
Fn
の引数型列の接頭辞P
それぞれについて、その長さがA1
の最小引数長であるものから、拡張クラスにname(...)
メソッドの多重定義を追加する。生成された各多重定義は、a1
の CallPolicies のコピーを使用してa1
のcall-expression
をP
とともに呼び出す。A1
の合法な接頭辞の最長のものがN
個の型を有しておりa1
がM
個のキーワードを保持しているとすると、各多重定義の先頭のN
-M
個の引数に使用される。それ以外の場合、
fn
に対してメソッドの多重定義を 1 つ構築する。Fn
は null であってはならない。fn
が関数ポインタである場合、第 1 引数はU
、U cv&
、U cv*
、U cv* const&
のいずれか(T*
がU*
に変換可能とする)でなければならない。a1
からa3
が与えられた場合、下表から任意の順番であってよい。上記以外で
fn
がメンバ関数へのポインタである場合、参照先はT
かその公開基底クラスでなければならない。a1
からa3
が与えられた場合、下表から任意の順番であってよい。それ以外の場合、
Fn
はobject
かその派生型でなければならない。a1
からa2
が与えられた場合、下表の 2 行目までから任意の順番であってよい。fn
が呼び出し可能でなければならない。名前
要件・型特性
効果
docstring
ntbs。
値は結果の多重定義メソッドの
__doc__
属性に束縛される。それ以前の多重定義でドキュメンテーション文字列が与えられている場合は、改行 2 文字と新しいドキュメンテーション文字列がそこに追加される。policies
CallPolicies のモデル
結果の多重定義メソッドの呼び出しポリシーとしてコピーが使用される。
keywords
fn
の引数長を超えることがないことを指定するkeyword-expression
の結果。結果の多重定義メソッドの呼び出しポリシーとしてコピーが使用される。
- 戻り値
*this
-
class_ &staticmethod(char const *name)
- 要件
name
は Python の識別子の名前付け規約にしたがった ntbs であり、多重定義がすべて定義済みのメソッドの名前。- 効果
既存の名前
x
の属性を Python のstaticmethod(x)
呼び出し結果で置換する。当該メソッドが静的でありオブジェクトを渡さないことを指定する。これは以下の Python 文と等価である。setattr(self, name, staticmethod(getattr(self, name)))
- 注意
staticmethod(name) 呼び出し後に def(name, ...) を呼び出すと、
RuntimeError
を送出する。- 戻り値
*this
-
template<class U>
class_ &setattr(char const *name, U const &u) - 要件
name
は Python の識別子の名前付け規約にしたがった ntbs。- 効果
u
を Python へ変換し、拡張クラスの属性辞書に追加する。PyObject_SetAttrString(this->ptr(), name, object(u).ptr())
- 戻り値
*this
-
template<class Get>
void add_property(char const *name, Get const &fget, char const *doc = 0) -
template<class Get, class Set>
void add_property(char const *name, Get const &fget, Set const &fset, char const *doc = 0)
-
template<class Get>
void add_static_property(char const *name, Get const &fget) -
template<class Get, class Set>
void add_static_property(char const *name, Get const &fget, Set const &fset) - 要件
name
は Python の識別子の名前付け規約にしたがった ntbs。- 効果
Boost.Python.StaticProperty オブジェクトを作成し、object(fget)(2 番目の形式では object(fset) も)をコンストラクタに渡す。最後にこのプロパティを構築中の Python のクラスオブジェクトに与えられた属性名
name
で追加する。StaticProperty は先頭のself
引数なしで呼び出せる Python の property クラスの特殊な派生クラスである。- 戻り値
*this
- 根拠
ユーザは、Python の属性アクセス構文で呼び出せる関数を容易にエクスポートできる。
-
template<class D>
class_ &def_readonly(char const *name, D T::* pm, char const *doc = 0) -
template<class D>
class_ &def_readonly(char const *name, D const &d) - 要件
name
は Python の識別子の名前付け規約にしたがった ntbs。- 効果
それぞれ、
this->add_property(name,
make_getter
(pm), doc);および
this->add_static_property(name,
make_getter
(d));- 戻り値
*this
- 根拠
ユーザは、Python から自然な構文で取得可能なクラスのデータメンバや自由変数を容易にエクスポートできる。
-
template<class D>
class_ &def_readwrite(char const *name, D T::* pm, char const *doc = 0) -
template<class D>
class_ &def_readwrite(char const *name, D &d) - 効果
それぞれ、
this->add_property(name,
make_getter
(pm),make_setter
(pm), doc);および
this->add_static_property(name,
make_getter
(d),make_setter
(pm));- 戻り値
*this
- 根拠
ユーザは、Python から自然な構文で取得・設定可能なクラスのデータメンバや自由変数を容易にエクスポートできる。
-
template<typename PickleSuite>
class_ &def_pickle(PickleSuite const&) - 要件
PickleSuite
はpickle_suite
の公開派生型でなければならない。- 効果
次の特殊な属性およびメソッドの合法な組み合わせを定義する:
__getinitargs__
、__getstate__
、__setstate__
、__getstate_manages_dict__
、__safe_for_unpickling__
、__reduce__
- 戻り値
*this
- 根拠
ユーザは、ラップしたクラスについて完全な pickle サポートを確立するための高水準インターフェイスを容易に使用できる。
-
class_ &enable_pickling()
- 効果
__reduce__
メソッドと__safe_for_unpickling__
属性を定義する。- 戻り値
*this
- 根拠
def_pickle
の軽量な代替。Python から pickle サポートの実装を有効にする。
bases<T1, T2, ...TN>
クラステンプレート
bases
クラステンプレートの概要
namespace boost { namespace python
{
template <T1 = unspecified,...Tn = unspecified>
struct bases
{};
}}
例
次のような C++ クラス宣言があるとすると、
class Foo : public Bar, public Baz
{
public:
Foo(int x, char const* y);
Foo(double);
std::string const& name() { return m_name; }
void name(char const*);
double value; // 公開データ
private:
...
};
対応する Boost.Python 拡張クラスは以下のように作成できる。
using namespace boost::python;
class_<Foo,bases<Bar,Baz> >("Foo",
"これは Foo のドキュメンテーション文字列。"
"Foo 拡張クラスの記述がここに入る",
init<int,char const*>(args("x","y"), "__init__ のドキュメンテーション文字列")
)
.def(init<double>())
.def("get_name", &Foo::get_name, return_internal_reference<>())
.def("set_name", &Foo::set_name)
.def_readwrite("value", &Foo::value)
;