[Python-Dev] GC and ExtensionClass (original) (raw)

Martin v. Loewis martin@loewis.home.cs.tu-berlin.de
Sun, 13 May 2001 00:32:10 +0200


Now, if you are using the 1.4 version of ExtensionClasses you might not have the tpflags field either (I don't know, I can't easily check) but the 1.5.2-compatible version of ExtensionClasses doesn't even require recompilation to work with Python 2.1.

I'll attach a copy below of the struct as defined in pygtk-0.7.0-unstable-dont-use.tar.gz (0.6.6 does not use extension classes). As you can see, it does not provide tp_flags, but has a field of tp_xxx4 for it.

That should work, except that it also has its 'methods' field where tp_traverse would go, and its class_flags field where tp_clear would go.

Now, you write

ExtensionClasses (at least recent versions that worked with 1.5.2) contain a copy of the type object up to and including the tpflags field, and the 2.1 code is careful not to use any newer fields without first checking the corresponding flag bit.

In this generality, it is apparently not true: Modules/gcmodule.c has, in delete_garbage,

        if ((clear = op->ob_type->tp_clear) != NULL) {

... traverse = PyObject_FROM_GC(gc)->ob_type->tp_traverse; (void) traverse(PyObject_FROM_GC(gc), (visitproc)visit_decref, NULL);

which does not check any flags. That still shouldn't cause any problems, since the Gtk objects should never end up in the GC lists - but may be I'm missing something.

Regards, Martin

typedef struct { PyObject_VAR_HEAD char tp_name; / For printing / int tp_basicsize, tp_itemsize; / For allocation */

/* Methods to implement standard operations */

destructor tp_dealloc;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
reprfunc tp_repr;

/* Method suites for standard classes */

PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;

/* More standard operations (at end for binary compatibility) */

hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Space for future expansion */
long tp_xxx3;
long tp_xxx4;

char *tp_doc; /* Documentation string */

#ifdef COUNT_ALLOCS /* these must be last */ int tp_alloc; int tp_free; int tp_maxalloc; struct _typeobject *tp_next; #endif PyMethodChain methods; long class_flags; PyObject *class_dictionary; PyObject *bases; PyObject *reserved; } PyExtensionClass;