Hi All,
The following extension module (AA) is a reduced example of what I'm doing
to make extension
classes in 2.2. I followed the examples given by typeobject.c. When I
"import AA,pdb" I get a crash in GC. Investigating further, I see this makes
sense: GC is enabled in class_metatype_object, yet class_type_object does
not follow the first rule of objects whose type has GC enabled:
"The memory for the object must be allocated using PyObject_GC_New()
or PyObject_GC_VarNew()."
So, I guess the question is, how does PyBaseObject_Type (also statically
allocated) get away with it?
TIA,
Dave
----------------
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include
PyTypeObject class_metatype_object = {
PyObject_HEAD_INIT(0)
0,
"Boost.Python.class",
PyType_Type.tp_basicsize,
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, // &PyType_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0,
// PyType_GenericNew /* tp_new */
};
// Get the metatype object for all extension classes.
PyObject* class_metatype()
{
if (class_metatype_object.tp_dict == 0)
{
class_metatype_object.ob_type = &PyType_Type;
class_metatype_object.tp_base = &PyType_Type;
if (PyType_Ready(&class_metatype_object))
return 0;
}
Py_INCREF(&class_metatype_object);
return (PyObject*)&class_metatype_object;
}
// Each extension instance will be one of these
typedef struct instance
{
PyObject_HEAD
void* objects;
} instance;
static void instance_dealloc(PyObject* inst)
{
instance* kill_me = (instance*)inst;
inst->ob_type->tp_free(inst);
}
PyTypeObject class_type_object = {
PyObject_HEAD_INIT(0) file://&class_metatype_object)
0,
"Boost.Python.instance",
sizeof(PyObject),
0,
instance_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, file://&PyBaseObject_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew
};
PyObject* class_type()
{
if (class_type_object.tp_dict == 0)
{
class_type_object.ob_type = (PyTypeObject*)class_metatype();
class_type_object.tp_base = &PyBaseObject_Type;
if (PyType_Ready(&class_type_object))
return 0;
}
Py_INCREF(&class_type_object);
return (PyObject*)&class_type_object;
}
PyObject* make_class()
{
PyObject* bases, *args, *mt, *result;
bases = PyTuple_New(1);
PyTuple_SET_ITEM(bases, 0, class_type());
args = PyTuple_New(3);
PyTuple_SET_ITEM(args, 0, PyString_FromString("AA"));
PyTuple_SET_ITEM(args, 1, bases);
PyTuple_SET_ITEM(args, 2, PyDict_New());
mt = class_metatype();
result = PyObject_CallObject(mt, args);
Py_XDECREF(mt);
Py_XDECREF(args);
return result;
}
static PyMethodDef SpamMethods[] = {
{NULL, NULL} /* Sentinel */
};
DL_EXPORT(void)
initAA()
{
PyObject *m, *d;
m = Py_InitModule("AA", SpamMethods);
d = PyModule_GetDict(m);
PyDict_SetItemString(d, "AA", make_class());
}
+---------------------------------------------------------------+
David Abrahams
C++ Booster (http://www.boost.org) O__ ==
Pythonista (http://www.python.org) c/ /'_ ==
resume: http://users.rcn.com/abrahams/resume.html (*) \(*) ==
email: david.abrahams@rcn.com
+---------------------------------------------------------------+