boost/python/register_ptr_to_python.hpp
はじめに
<boost/python/register_ptr_to_python.hpp>
は、スマートポインタから Python への変換を登録する関数テンプレート register_ptr_to_python
を提供する。結果の Python オブジェクトは変換したスマートポインタのコピーを保持するが、参照先のラップ済みコピーであるかのように振舞う。参照先の型が仮想関数を持ちそのクラスが動的(最派生)型を表現する場合、Python のオブジェクトは最派生型に対するラッパのインスタンスとなる。1 つの参照先クラスに対して 2 つ以上のスマートポインタ型を登録可能である。
Python の X
オブジェクトを smart_ptr<X>&
(非 const 参照)へ変換するため、組み込む C++ オブジェクトは smart_ptr<X>
が保持しなければならない。またラップしたオブジェクトを Python からコンストラクタを呼び出して作成するとき、どのように保持するかは class_<>
インスタンスの HeldType
引数で決められることに注意していただきたい。
関数
-
template<class P>
void register_ptr_to_python() - 要件
P
が Dereferenceable。- 効果
P
のインスタンスの Python への変換を可能にする。
例
C++ のラッパコード
以下の例は仮想関数を持つクラス A
と、boost::shared_ptr<A>
を扱う関数を持つモジュールである。
struct A
{
virtual int f() { return 0; }
};
shared_ptr<A> New() { return shared_ptr<A>( new A() ); }
int Ok( const shared_ptr<A>& a ) { return a->f(); }
int Fail( shared_ptr<A>& a ) { return a->f(); }
struct A_Wrapper: A
{
A_Wrapper(PyObject* self_): self(self_) {}
int f() { return call_method<int>(self, "f"); }
int default_f() { return A::f(); }
PyObject* self;
};
BOOST_PYTHON_MODULE(register_ptr)
{
class_<A, A_Wrapper>("A")
.def("f", &A::f, &A_Wrapper::default_f)
;
def("New", &New);
def("Ok", &Call);
def("Fail", &Fail);
register_ptr_to_python< shared_ptr<A> >();
}
Python のコード
>>> from register_ptr import *
>>> a = A()
>>> Ok(a) # OK 、shared_ptr<A> として渡した
0
>>> Fail(a) # shared_ptr<A>& として渡してしまった(Python 内で作成したのだった!)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: bad argument type for built-in operation
>>>
>>> na = New() # ここで "na" は実際は shared_ptr<A>
>>> Ok(a)
0
>>> Fail(a)
0
>>>
shared_ptr<A>
を以下のように登録したとすると、
class_<A, A_Wrapper, shared_ptr<A> >("A")
.def("f", &A::f, &A_Wrapper::default_f)
;
shared_ptr<A>
を shared_ptr<A_Wrapper>
に変換しようとするとエラーになる。
>>> a = New()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr<struct A>
>>>