これが私があなたが望むと思うことをする小さな例です。手順全体は、Pythonで特定のタイプのインスタンスを構築するときに、Boost.Pythonに実際に別のクラスを使用するように指示し、カスタムのコンストラクターに最初の引数としてPythonオブジェクトを渡すように指示する「ホルダー」クラスの使用を中心にしています。ラッパークラス。あなたはここでより多くの情報を見つけることができます:
http://www.boost.org/doc/libs/1_48_0/libs/python/doc/v2/class.html
(特に「HeldTypeセマンティクス」の説明を参照してください)。
#include "boost/python.hpp"
namespace bp = boost::python;
class Base {
public:
virtual double go(int x) const = 0;
virtual ~Base() {}
};
class PyBase : public Base {
public:
explicit PyBase(PyObject* self) : _self(self) {
Py_INCREF(_self); // THIS LEAKS MEMORY IF THERE'S NO DECREF!
}
virtual double go(int x) const {
return bp::call_method<double>(_self, "go", x);
}
private:
PyObject * _self;
};
BOOST_PYTHON_MODULE(example) {
bp::class_<Base,PyBase,boost::noncopyable>(
"Base",
bp::init<>() // the PyObject* arg is implicit
)
.def("go", &PyBase::go)
;
}
ただし、いくつかの注意点があります。
go
から継承するPythonで実装しないとBase
、無限再帰に関する役に立たないPython例外メッセージが表示されます。また、デフォルトの実装がある場合に仮想関数をC ++にフォールバックする方法もわかりません(bp::wrapper
非常によく似た処理を行うのコードを見ると、おそらく理解できます)。
参照またはポインターによってC++関数からオブジェクトを返す場合、返されたインスタンスが実際に最初からPyBaseオブジェクトでない限り、Base
オブジェクトを含むPythonオブジェクトはありません(それについて考えると、PyBase
コース)。
値で返す場合は、呼び出しからテンプレート引数をPyObject*
削除する前に、最初の引数としてをとるコピーコンストラクターを追加する必要があります。boost::noncopyable
bp::class_
コンストラクターのPy_INCREF
ステートメントは、「コード」がこのオブジェクトへの追加の参照を取得していることをPythonに通知します。しかし、対応するものをどのように追加するかは私にはわかりません。オブジェクトがすべてある場合、後でそれを取得する方法はありませPy_DECREF
ん。std::map
Base*
PyObject*
上記の問題を回避する1つの方法は、bp::handle<>
またはのコンテナーをbp::object
作成し、それらの1つを作成self
してコンテナーに入れることです。ただし、その場合、静的デストラクタ時にPythonデストラクタが呼び出されるとセグメンテーション違反が発生するため、プログラムが終了する前にこれらのコンテナが空になっていることを確認する必要があります。