コンセプト

CallPolicies コンセプト

はじめに

CallPolicies コンセプトのモデルは、Boost.Python が生成した Python の呼び出し可能オブジェクトの振る舞いを、関数やメンバ関数ポインタのようなラップした C++ オブジェクトに対して特殊化するのに使用する。以下の 4 つの振る舞いを提供する。

  1. precall ― ラップしたオブジェクトが呼び出される前の Python 引数タプルの管理

  2. result_converter ― C++ 戻り値の処理

  3. postcall ― ラップしたオブジェクトが呼び出された後の Python 引数タプルと戻り値の管理

  4. extract_return_type ― 与えられたシグニチャ型並びから戻り値の型を抽出するメタ関数

CallPolicies の合成

ユーザが同じ呼び出し可能オブジェクトで複数の CallPolicies モデルを使用可能にするため、Boost.Python の CallPolicies クラステンプレートは再帰的に合成可能な数珠繋ぎのインターフェイスを提供する。このインターフェイスは省略可能なテンプレート引数 Base を取り、既定は default_call_policies である。慣習に従って、Baseprecall 関数はより外側のテンプレートが与えた precall 関数の後で呼び出され、Basepostcall 関数はより外側のテンプレートの postcall 関数より前に呼び出される。より外側のテンプレートで result_converter が与えられた場合、Base で与えた result_converter上書きされる。例えば return_internal_reference を見よ。

コンセプトの要件

CallPolicies コンセプト

以下の表で x は CallPolicies のモデルである型 P のオブジェクト、a は Python の引数タプルオブジェクトを指す PyObject*r は「予備的な」戻り値オブジェクトを参照する PyObject* を表す。

結果・セマンティクス

x.precall(a)

bool へ変換可能

失敗時は false および PyErr_Occurred() != 0 、それ以外は true

P::result_converter

ResultConverterGenerator のモデル</td>

「予備的な」戻り値オブジェクトを生成する MPL の単項メタ関数クラス

x.postcall(a, r)

PyObject* へ変換可能

失敗時は 0 および PyErr_Occurred() != 0。例外送出中であっても「参照を保持」しなければならない。言い換えると、r を返さない場合はその参照カウントを減らさなければならず、別の生存しているオブジェクトを返す場合はその参照カウントを増やさなければならない。

P::extract_return_type

Metafunction のモデル

与えられたシグニチャから戻り値の型を抽出する MPL の単項 Metafunction。既定では mpl::front から導出する。

CallPolicies のモデルは CopyConstructible であることが要求される。

Dereferenceable コンセプト

はじめに

Dereferenceable 型のインスタンスは lvalue へアクセスするポインタのように使用できる。

コンセプトの要件

Dereferenceable コンセプト

以下の表で T は Dereferenceable のモデル、x は型 T のオブジェクトを表す。またポインタはすべて Dereferenceable とする。

結果

操作上のセマンティクス

get_pointer(x)

pointee<>::type* へ変換可能

&*x かヌルポインタ

Extractor コンセプト

はじめに

Extractor は、Boost.Python が Python オブジェクトから C++ オブジェクトを抽出するのに使用するクラスである。典型的には、「伝統的な」Python 拡張型について from_python 変換を定義するのに使用する。

コンセプトの要件

Extractor コンセプト

以下の表で X は Extractor のモデル、a は Python オブジェクト型のインスタンスを表す。

セマンティクス

X::execute(a)

非 void

抽出する C++ オブジェクトを返す。execute 関数は多重定義してはならない。

&a.ob_type

PyTypeObject**

PyObject とレイアウト互換なオブジェクトの ob_type フィールドを指す。

注意事項

簡単に言うと、Extractor の execute メンバは多重定義のない、Python オブジェクト型を 1 つだけ引数にとる静的関数でなければならない。PyObject から公開派生した(かつあいまいでない継承関係にある)型、および PyObject とレイアウト互換な POD 型もこの Python オブジェクト型に含まれる。

HolderGenerator コンセプト

はじめに

HolderGenerator はその引数のインスタンスを、ラップした C++ クラスインスタンス内に保持するのに適した型を返す単項メタ関数クラスである。

コンセンプトの要件

HolderGenerator コンセプト

以下の表で G は HolderGenerator のモデル型、X はクラス型を表す。

要件

G::apply<X>::type

X のオブジェクトを保持できる instance_holder の具象派生クラス。

ResultConverter/ResultConverterGenerator コンセプト

はじめに

T に対する ResultConverter は、型 T の C++ 戻り値を to_python 変換するのにそのインスタンスが使用可能な型である。ResultConverterGenerator は、C++ 関数の戻り値型が与えられたときにその型に対する ResultConverter を返す MPL の単項メタ関数クラスである。Boost.Python における ResultConverter は一般的にライブラリの変換器レジストリを探索して適切な変換器を探すが、レジストリを使用しない変換器もありうる。

コンセプトの要件

ResultConverter コンセプト

以下の表で C は型 R に対する ResultConverter 、c は型 C のオブジェクト、r は型 R のオブジェクトを表す。

セマンティクス

C c;

C のオブジェクトを構築する。

c.convertible()

bool へ変換可能

R の値から Python オブジェクトへの変換が不可能な場合は false

c(r)

PyObject* へ変換可能

v に対応する Python オブジェクトへのポインタ。rto_python 変換不可能な場合は 0 で、PyErr_Occurred は非 0 を返すはずである。

c.get_pytype()

PyTypeObject const*

変換の結果に対応する Python の型オブジェクトへのポインタか 0。ドキュメンテーションの生成に使用する。0 を返した場合はドキュメンテーション内で生成された型は「object」になる。

ResultConverterGenerator コンセプト

以下の表で G は ResultConverterGenerator 型、R は C++ 関数の戻り値型。

要件

G::apply<R>::type

R に対する ResultConverter 型。

ObjectWrapper/TypeWrapper コンセプト

はじめに

Python オブジェクトを管理するクラスと Python 風の構文をサポートするクラスを表現する、2 つのコンセプトを定義する。

コンセプトの要件

ObjectWrapper コンセプト

ObjectWrapper コンセプトのモデルは公開アクセス可能な基底クラスとして object を持ち、特殊な構築の振る舞いとメンバ関数(テンプレートメンバ関数であることが多い)による便利な機能を提供する。戻り値の型 R 自身が TypeWrapper である場合を除いて、次のメンバ関数呼び出し形式は

x.some_function(a1, a2,...an)

常に以下と同じセマンティクスを持つ。

extract<R>(x.attr("some_function")(object(a1), object(a2),...object(an)))()

RTypeWrapper である場合、戻り値の型は直接以下により構築する。

x.attr("some_function")(object(a1), object(a2),...object(an)).ptr()

(ただし以下の注意も見よ。)

TypeWrapper コンセプト

TypeWrapper は個々の Python の型 X と一体となった ObjectWrapper の改良版である。TypeWrapper として T があるとすると、

T(a1, a2,...an)

上記の合法なコンストラクタ式は、以下に相当する引数列で X を呼び出した結果を管理する新しい T オブジェクトを構築する。

object(a1), object(a2),...object(an)

ラップした C++ 関数の引数、あるいは extract<> のテンプレート引数として使用した場合、対応する Python 型のインスタンスだけがマッチするとみなされる。

注意

戻り値の型が TypeWrapper である場合の特殊なメンバ関数の呼び出し規則は結論として、返されたオブジェクトが不適切な型の Python オブジェクトを管理している可能がある。これは大抵の場合、深刻な問題とはならない(最悪の場合の結果は、エラーが実行時に検出される場合、つまり他のあらゆる場合よりも少し遅いタイミングだ)。このようなことが起こる例として、dict のメンバ関数 itemslist 型のオブジェクトを返すことに注意していただきたい。今、ユーザがこの dict の派生クラスを Python 内で定義すると、

>>> class mydict(dict):
...     def items(self):
...         return tuple(dict.items(self)) # タプルを返す

mydict のインスタンスは dict のインスタンスでもあるため、ラップした C++ 関数の引数として使用すると、boost::python::dict は Python の mydict 型オブジェクトも受け取る。このオブジェクトに対して items() を呼び出すと、実際には Python のタプルを保持した boost::python::list のインスタンスが返る。このオブジェクトで続けて list のメソッド(例えば append 等、変更を伴う操作)を使用すると、同じことを Python で行った場合と同様の例外が送出する。