Adding GC Support to a Python Type

Note: I have only lightly tested this code (and only with 2.2 and 2.1). If it does or does not work for you, please let me know.

Add the following code at the beginning of the extension module.


#if defined(Py_TPFLAGS_GC) && !defined(Py_TPFLAGS_HAVE_GC)
/* Python 2.2 GC compatibility macros */
#define Py_TPFLAGS_HAVE_GC Py_TPFLAGS_GC
#define PyObject_GC_New PyObject_New
#define PyObject_GC_Del PyObject_Del
#define PyObject_GC_Track PyObject_GC_Init
#define PyObject_GC_UnTrack PyObject_GC_Fini
#endif

#ifndef Py_TPFLAGS_HAVE_GC
/* no GC */
#define Py_TPFLAGS_HAVE_GC 0
#define PyObject_GC_New PyObject_New
#define PyObject_GC_Del PyObject_Del
#define PyObject_GC_Track
#define PyObject_GC_UnTrack
#define PyGC_HEAD_SIZE 0
typedef int (*visitproc)(PyObject *, void *);
typedef int (*traverseproc)(PyObject *, visitproc, void *);
#endif

This allows you to use the 2.2 GC API and have it work with 2.0 and 2.1 and be a no-op for Python < 2.0. Note that you still have to include PyGC_HEAD_SIZE in the tp_basicsize calculation.

To review: use PyObject_GC_New and PyObject_GC_Del to allocate and dellocate the object. Call PyObject_GC_Track before returning the object from the "new" function and PyObject_GC_UnTrack before starting to deallocate it. Include Py_TPFLAGS_HAVE_GC with the tp_flags. Add PyGC_HEAD_SIZE to tp_basicsize. Define the tp_traverse method and optionally the tp_clear method.