コンセプト
目次
CallPolicies コンセプト
はじめに
CallPolicies コンセプトのモデルは、Boost.Python が生成した Python の呼び出し可能オブジェクトの振る舞いを、関数やメンバ関数ポインタのようなラップした C++ オブジェクトに対して特殊化するのに使用する。以下の 4 つの振る舞いを提供する。
precall
― ラップしたオブジェクトが呼び出される前の Python 引数タプルの管理result_converter
― C++ 戻り値の処理postcall
― ラップしたオブジェクトが呼び出された後の Python 引数タプルと戻り値の管理extract_return_type
― 与えられたシグニチャ型並びから戻り値の型を抽出するメタ関数
CallPolicies の合成
ユーザが同じ呼び出し可能オブジェクトで複数の CallPolicies モデルを使用可能にするため、Boost.Python の CallPolicies クラステンプレートは再帰的に合成可能な数珠繋ぎのインターフェイスを提供する。このインターフェイスは省略可能なテンプレート引数 Base
を取り、既定は default_call_policies
である。慣習に従って、Base
の precall
関数はより外側のテンプレートが与えた precall
関数の後で呼び出され、Base
の postcall
関数はより外側のテンプレートの postcall
関数より前に呼び出される。より外側のテンプレートで result_converter
が与えられた場合、Base
で与えた result_converter
は上書きされる。例えば return_internal_reference
を見よ。
コンセプトの要件
CallPolicies コンセプト
以下の表で x
は CallPolicies のモデルである型 P
のオブジェクト、a
は Python の引数タプルオブジェクトを指す PyObject*
、r
は「予備的な」戻り値オブジェクトを参照する PyObject*
を表す。
式 |
型 |
結果・セマンティクス |
---|---|---|
x.precall(a) |
|
失敗時は |
P::result_converter |
ResultConverterGenerator のモデル</td> |
「予備的な」戻り値オブジェクトを生成する MPL の単項メタ関数クラス。 |
x.postcall(a, r) |
|
失敗時は |
P::extract_return_type |
Metafunction のモデル |
与えられたシグニチャから戻り値の型を抽出する MPL の単項 Metafunction。既定では |
CallPolicies のモデルは CopyConstructible であることが要求される。
Dereferenceable コンセプト
はじめに
Dereferenceable 型のインスタンスは lvalue へアクセスするポインタのように使用できる。
コンセプトの要件
Dereferenceable コンセプト
以下の表で T
は Dereferenceable のモデル、x
は型 T
のオブジェクトを表す。またポインタはすべて Dereferenceable とする。
式 |
結果 |
操作上のセマンティクス |
---|---|---|
get_pointer(x) |
|
&*x かヌルポインタ |
Extractor コンセプト
はじめに
Extractor は、Boost.Python が Python オブジェクトから C++ オブジェクトを抽出するのに使用するクラスである。典型的には、「伝統的な」Python 拡張型について from_python
変換を定義するのに使用する。
コンセプトの要件
Extractor コンセプト
以下の表で X
は Extractor のモデル、a
は Python オブジェクト型のインスタンスを表す。
式 |
型 |
セマンティクス |
---|---|---|
X::execute(a) |
非 void |
抽出する C++ オブジェクトを返す。 |
&a.ob_type |
|
注意事項
簡単に言うと、Extractor の execute
メンバは多重定義のない、Python オブジェクト型を 1 つだけ引数にとる静的関数でなければならない。PyObject
から公開派生した(かつあいまいでない継承関係にある)型、および PyObject
とレイアウト互換な POD 型もこの Python オブジェクト型に含まれる。
HolderGenerator コンセプト
はじめに
HolderGenerator はその引数のインスタンスを、ラップした C++ クラスインスタンス内に保持するのに適した型を返す単項メタ関数クラスである。
コンセンプトの要件
HolderGenerator コンセプト
以下の表で G
は HolderGenerator のモデル型、X
はクラス型を表す。
式 |
要件 |
---|---|
G::apply<X>::type |
型 |
ResultConverter/ResultConverterGenerator コンセプト
はじめに
型 T
に対する ResultConverter は、型 T
の C++ 戻り値を to_python
変換するのにそのインスタンスが使用可能な型である。ResultConverterGenerator は、C++ 関数の戻り値型が与えられたときにその型に対する ResultConverter を返す MPL の単項メタ関数クラスである。Boost.Python における ResultConverter は一般的にライブラリの変換器レジストリを探索して適切な変換器を探すが、レジストリを使用しない変換器もありうる。
コンセプトの要件
ResultConverter コンセプト
以下の表で C
は型 R
に対する ResultConverter 、c
は型 C
のオブジェクト、r
は型 R
のオブジェクトを表す。
式 |
型 |
セマンティクス |
---|---|---|
|
|
|
c.convertible() |
|
|
c(r) |
|
|
c.get_pytype() |
|
変換の結果に対応する Python の型オブジェクトへのポインタか |
ResultConverterGenerator コンセプト
以下の表で G
は ResultConverterGenerator 型、R
は C++ 関数の戻り値型。
式 |
要件 |
---|---|
G::apply<R>::type |
|
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
)))()
R
が TypeWrapper
である場合、戻り値の型は直接以下により構築する。
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
のメンバ関数 items
が list
型のオブジェクトを返すことに注意していただきたい。今、ユーザがこの 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 で行った場合と同様の例外が送出する。