オブジェクトの作成と破棄にnew演算子とdelete演算子を使用したいと思います。Python C-APIオブジェクトの割り当て
問題は、Pythonがいくつかの段階に分けるようです。作成のためのtp_new、tp_init、およびtp_alloc、破棄のためのtp_del、tp_free、およびtp_deallocしかし、C++には、オブジェクトを割り当てて完全に構築し、そのオブジェクトを破棄したり、割り当てを解除したりする新しいものがあります。
どのpython tp_ *メソッドを提供する必要があり、どのようにしなければなりませんか?
また、「PyObject * obj = new MyExtensionObject(args);」などのオブジェクトを直接C++で作成できます。これをサポートするために何らかの方法で新しい演算子をオーバーロードする必要がありますか?
また、私の拡張機能の種類をPythonでサブクラス化できるようにしたいと思いますが、これをサポートするために何か特別なことはありますか?
私はpython 3.0.1を使用しています。テクスチャオブジェクトを作成して、作成後に内容を変更するなど、オブジェクトのサイズをあまりにも変更可能にしているようですが、サイズ、サイズなどの基本的な側面を変更してください。 bitdeptなどは、そのようなものが修正されていると仮定して、既存のC++のものをたくさん破ります)。私がそれを実装していないと、それは単に、構築された後に(または少なくともタプルのように呼び出しを無視して)__init__を呼び出す人々を止めるでしょう。または、同じオブジェクトに対してtp_initが複数回呼び出された場合は、例外をスローするフラグが必要ですか?
それ以外は、私はiveが残りの大部分を分類していると思います。
extern "C"
{
//creation + destruction
PyObject* global_alloc(PyTypeObject *type, Py_ssize_t items)
{
return (PyObject*)new char[type->tp_basicsize + items*type->tp_itemsize];
}
void global_free(void *mem)
{
delete[] (char*)mem;
}
}
template<class T> class ExtensionType
{
PyTypeObject *t;
ExtensionType()
{
t = new PyTypeObject();//not sure on this one, what is the "correct" way to create an empty type object
memset((void*)t, 0, sizeof(PyTypeObject));
static PyVarObject init = {PyObject_HEAD_INIT, 0};
*((PyObject*)t) = init;
t->tp_basicsize = sizeof(T);
t->tp_itemsize = 0;
t->tp_name = "unknown";
t->tp_alloc = (allocfunc) global_alloc;
t->tp_free = (freefunc) global_free;
t->tp_new = (newfunc) T::obj_new;
t->tp_dealloc = (destructor)T::obj_dealloc;
...
}
...bunch of methods for changing stuff...
PyObject *Finalise()
{
...
}
};
template <class T> PyObjectExtension : public PyObject
{
...
extern "C" static PyObject* obj_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
{
void *mem = (void*)subtype->tp_alloc(subtype, 0);
return (PyObject*)new(mem) T(args, kwds)
}
extern "C" static void obj_dealloc(PyObject *obj)
{
~T();
obj->ob_type->tp_free(obj);//most of the time this is global_free(obj)
}
...
};
class MyObject : PyObjectExtension<MyObject>
{
public:
static PyObject* InitType()
{
ExtensionType<MyObject> extType();
...sets other stuff...
return extType.Finalise();
}
...
};
配置は直感的ですが、残念ながら 'new(p)Class(args);'はコンストラクタを呼び出す前にゼロ初期化を行い、Pythonの割り当て/初期化コードがオブジェクトに入れた値を消去しますメモリ(例えば、参照カウント)。これとは別に、 'new char [n]'を使うと、保証されたメモリアライメントが1にすぎないので、構造をオーバーレイすることは危険です。 –