Python から呼び出すために、いくつかの C++ クラスの周りに薄いラッパーを作成しようとしています。具体的な問題は、virtual
以下のコメントが外されている場合、インタープリターを作成しようとするとFoo()
クラッシュすることです。この問題を解決するために、このコードを Boost::python、SWIG、または Pyxxx として書き直すことに興味はありません。これは、より大きなシステムからの抜粋です。これらのライブラリのいずれかがこの問題を解決する場合でも、なぜそうなるのか知りたいです。彼らがそれをどのように実装しているか知りたいです。extern "C"
拡張モジュールをセットアップしてシステムに型を登録すると、Python インタープリターからの呼び出しは、Python 型のスロットに登録するクラスの静的メンバーを使用するか、または単に持つだけで、問題なく機能します。
メンバーを仮想として宣言すると、それを (Python インタープリターからの呼び出し内で) 呼び出そうとすると、不正なメモリ アクセスでクラッシュが発生します。アクセスされるアドレスは、クラス メンバーをポインターとして出力した場合に得られるオフセットです。従うべき特定のコードがありますが、基本的な質問は次のとおりです。Python によって呼び出される C ランタイム環境の何かが、仮想クラス メンバー関数のディスパッチを台無しにしますか? Python は v2.6.7 で、C++ 拡張機能は GCC 4.2.1 でコンパイルされています。Boost::python がこれをサポートしていることを示唆する関連する質問があります。彼らはそれを直接行っていますか、それともクラス メンバー関数を介してシミュレートしていますか?
// PythonType is a class that inherits from PyTypeObject and fills in defaults ...
extern "C" int initHook(PyObject *self, PyObject *args, PyObject *kwds);
class Foo
{
public:
static PythonType thePyType;
static void registerType(PyObject *module)
{
thePyType.tp_init = initHook;
PyType_Ready(&thePyType);
PyModule_AddObject(module, thePyType.tp_name, (PyObject*)&thePyType);
}
/*virtual*/ void insert()
{
printf("Inserted\n");
}
};
PythonType Foo::thePyType("Foo",sizeof(Foo));
extern "C" {
int initHook(PyObject *self, PyObject *args, PyObject *kwds)
{
((Foo*)self)->insert();
}
}