[Python-Dev] GC and ExtensionClass

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 tp_flags 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 tp_flags
> 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;