Extending and Embedding Python, Release 3.9.5 (continued from previous page) PyObject *tp_weaklist; destructor tp_del; /* Type attribute cache version tag. Added in version 2.6 */ unsigned int tp_version_tag; destructor tp_finalize; } PyTypeObject; Now that’s a lot of methods. Don’t worry too much though – if you have a type you want to define, the chances are very good that you will only implement a handful of these. As you probably expect by now, we’re going to go over this and give more information about the various handlers. We won’t go in the order they are defined in the structure, because there is a lot of historical baggage that impacts the ordering of the fields. It’s often easiest to find an example that includes the fields you need and then change the values to suit your new type. const char *tp_name; /* For printing */ The name of the type – as mentioned in the previous chapter, this will appear in various places, almost entirely for diagnostic purposes. Try to choose something that will be helpful in such a situation! Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ These fields tell the runtime how much memory to allocate when new objects of this type are created. Python has some built-in support for variable length structures (think: strings, tuples) which is where the$_{tp_itemsize}$ field comes in. This will be dealt with later. const char *tp_doc; Here you can put a string (or its address) that you want returned when the Python script references$_{obj.__doc__}$ to retrieve the doc string. Now we come to the basic type methods – the ones most extension types will implement. destructor tp_dealloc; This function is called when the reference count of the instance of your type is reduced to zero and the Python interpreter wants to reclaim it. If your type has memory to free or other clean-up to perform, you can put it here. The object itself needs to be freed here as well. Here is an example of this function: static void newdatatype_dealloc(newdatatypeobject *obj) { free(obj->obj_UnderlyingDatatypePtr); Py_TYPE(obj) ->tp_free(obj); } 2.3.1 Finalization and De-allocation One important requirement of the deallocator function is that it leaves any pending exceptions alone. This is important since deallocators are frequently called as the interpreter unwinds the Python stack; when the stack is unwound due to an exception (rather than normal returns), nothing is done to protect the deallocators from seeing that an exception has already been set. Any actions which a deallocator performs which may cause additional Python code to be executed may detect that an exception has been set. This can lead to misleading errors from the interpreter. The proper way to protect against this is to save a pending exception before performing the unsafe action, and restoring it when done. This can be done using the$_{PyErr_Fetch()}$ and$_{PyErr_Restore()}$ functions: 47 2.3. Defining Extension Types: Assorted Topics