I want to use new and delete operators to create and destroy my objects.
The problem is that python breaks it down into several stages. tp_new, tp_init and tp_alloc to create and tp_del, tp_free and tp_dealloc to destroy. However, C ++ only has a new one that selects and completely constructs the object and deletes that destroys and frees the object.
Which of the tp_ * python methods do I need to provide and what should they do?
I also want to be able to create an object directly in C ++, for example, "PyObject" obj = new MyExtensionObject (args); "Will I also need to somehow overload the new operator to support this?
I would also like to be able to subclass my extension types in python, is there anything special I need to do to support this?
I am using python 3.0.1.
EDIT: ok, tp_init seems to make the objects too oversized for what I am doing (e.g. take a Texture object, changing the contents after creation in order, but change its fundamental aspects like size, bitdept, etc. existing material C ++, which assumes that such things are fixed). If I don't implement it, it just stops people calling __init__ AFTER the creation (or at least ignoring the call, such as a tuple). Or should I have some flag that throws an exception or somthing if tp_init is called more than once on the same object?
, , , .
extern "C"
{
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();
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);
}
...
};
class MyObject : PyObjectExtension<MyObject>
{
public:
static PyObject* InitType()
{
ExtensionType<MyObject> extType();
...sets other stuff...
return extType.Finalise();
}
...
};