Assume we have the type Noddy
as defined in the tutorial on writing C extension modules for Python. Now we want to create a derived type, overwriting only the __new__()
method of Noddy
.
Currently I use the following approach (error checking stripped for readability):
PyTypeObject *BrownNoddyType =
(PyTypeObject *)PyType_Type.tp_alloc(&PyType_Type, 0);
BrownNoddyType->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
BrownNoddyType->tp_name = "noddy.BrownNoddy";
BrownNoddyType->tp_doc = "BrownNoddy objects";
BrownNoddyType->tp_base = &NoddyType;
BrownNoddyType->tp_new = BrownNoddy_new;
PyType_Ready(BrownNoddyType);
This works, but I'm not sure if it is The Right Way To Do It. I would have expected that I have to set the Py_TPFLAGS_HEAPTYPE
flag, too, because I dynamically allocate the type object on the heap, but doing so leads to a segfault in the interpreter.
I also thought about explicitly calling type()
using PyObject_Call()
or similar, but I discarded the idea. I would need to wrap the function BrownNoddy_new()
in a Python function object and create a dictionary mapping __new__
to this function object, which seems silly.
What is the best way to go about this? Is my approach correct? Is there an interface function I missed?
Update
There are two threads on a related topic on the python-dev mailing list (1) (2). From these threads and a few experiments I deduce that I shouldn't set Py_TPFLAGS_HEAPTYPE
unless the type is allocated by a call to type()
. There are different recommendations in these threads whether it is better to allocate the type manually or to call type()
. I'd be happy with the latter if only I knew what the recommended way to wrap the C function that is supposed to go in the tp_new
slot is. For regular methods this step would be easy -- I could just use PyDescr_NewMethod()
to get a suitable wrapper object. I don't know how to create such a wrapper object for my __new__()
method, though -- maybe I need the undocumented function PyCFunction_New()
to create such a wrapper object.