diff Modules/_ctypes/callbacks.c @ 46549:90e2146cb8a3

Merged revisions 62481 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r62481 | thomas.heller | 2008-04-24 20:14:19 +0200 (Do, 24 Apr 2008) | 3 lines Remove cyclic reference in CFuncPtr instances; see issue #2682. Backport candidate for the release25-maint branch. ........
author Thomas Heller <theller@ctypes.org>
date Thu, 24 Apr 2008 18:39:36 +0000
parents ef2d3bf8383d
children 948bea96dd20
line wrap: on
line diff
--- a/Modules/_ctypes/callbacks.c	Thu Apr 24 18:26:53 2008 +0000
+++ b/Modules/_ctypes/callbacks.c	Thu Apr 24 18:39:36 2008 +0000
@@ -7,6 +7,73 @@
 #endif
 #include "ctypes.h"
 
+/**************************************************************/
+
+static CThunkObject_dealloc(PyObject *_self)
+{
+	CThunkObject *self = (CThunkObject *)_self;
+	Py_XDECREF(self->converters);
+	Py_XDECREF(self->callable);
+	Py_XDECREF(self->restype);
+	if (self->pcl)
+		FreeClosure(self->pcl);
+	PyObject_Del(self);
+}
+
+static int
+CThunkObject_traverse(PyObject *_self, visitproc visit, void *arg)
+{
+	CThunkObject *self = (CThunkObject *)_self;
+	Py_VISIT(self->converters);
+	Py_VISIT(self->callable);
+	Py_VISIT(self->restype);
+	return 0;
+}
+
+static int
+CThunkObject_clear(PyObject *_self)
+{
+	CThunkObject *self = (CThunkObject *)_self;
+	Py_CLEAR(self->converters);
+	Py_CLEAR(self->callable);
+	Py_CLEAR(self->restype);
+	return 0;
+}
+
+PyTypeObject CThunk_Type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	"_ctypes.CThunkObject",
+	sizeof(CThunkObject),			/* tp_basicsize */
+	sizeof(ffi_type),			/* tp_itemsize */
+	CThunkObject_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,			/* tp_flags */
+	"CThunkObject",				/* tp_doc */
+	CThunkObject_traverse,			/* tp_traverse */
+	CThunkObject_clear,	       		/* tp_clear */
+	0,					/* tp_richcompare */
+	0,					/* tp_weaklistoffset */
+	0,					/* tp_iter */
+	0,					/* tp_iternext */
+	0,					/* tp_methods */
+	0,					/* tp_members */
+};
+
+/**************************************************************/
+
 static void
 PrintError(char *msg, ...)
 {
@@ -244,32 +311,56 @@
 			void **args,
 			void *userdata)
 {
-	ffi_info *p = userdata;
+	CThunkObject *p = (CThunkObject *)userdata;
 
 	_CallPythonObject(resp,
-			  p->restype,
+			  p->ffi_restype,
 			  p->setfunc,
 			  p->callable,
 			  p->converters,
 			  args);
 }
 
-ffi_info *AllocFunctionCallback(PyObject *callable,
-				PyObject *converters,
-				PyObject *restype,
-				int is_cdecl)
+static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
+{
+	CThunkObject *p;
+	int i;
+
+	p = PyObject_NewVar(CThunkObject, &CThunk_Type, nArgs);
+	if (p == NULL) {
+		PyErr_NoMemory();
+		return NULL;
+	}
+
+	p->pcl = NULL;
+	memset(&p->cif, 0, sizeof(p->cif));
+	p->converters = NULL;
+	p->callable = NULL;
+	p->setfunc = NULL;
+	p->ffi_restype = NULL;
+	
+	for (i = 0; i < nArgs + 1; ++i)
+		p->atypes[i] = NULL;
+	return p;
+}
+
+CThunkObject *AllocFunctionCallback(PyObject *callable,
+				    PyObject *converters,
+				    PyObject *restype,
+				    int is_cdecl)
 {
 	int result;
-	ffi_info *p;
+	CThunkObject *p;
 	Py_ssize_t nArgs, i;
 	ffi_abi cc;
 
 	nArgs = PySequence_Size(converters);
-	p = (ffi_info *)PyMem_Malloc(sizeof(ffi_info) + sizeof(ffi_type) * (nArgs));
-	if (p == NULL) {
-		PyErr_NoMemory();
+	p = CThunkObject_new(nArgs);
+	if (p == NULL)
 		return NULL;
-	}
+
+	assert(CThunk_CheckExact((PyObject *)p));
+
 	p->pcl = MallocClosure();
 	if (p->pcl == NULL) {
 		PyErr_NoMemory();
@@ -285,9 +376,11 @@
 	}
 	p->atypes[i] = NULL;
 
+	Py_INCREF(restype);
+	p->restype = restype;
 	if (restype == Py_None) {
 		p->setfunc = NULL;
-		p->restype = &ffi_type_void;
+		p->ffi_restype = &ffi_type_void;
 	} else {
 		StgDictObject *dict = PyType_stgdict(restype);
 		if (dict == NULL || dict->setfunc == NULL) {
@@ -296,7 +389,7 @@
 		  goto error;
 		}
 		p->setfunc = dict->setfunc;
-		p->restype = &dict->ffi_type_pointer;
+		p->ffi_restype = &dict->ffi_type_pointer;
 	}
 
 	cc = FFI_DEFAULT_ABI;
@@ -320,16 +413,14 @@
 		goto error;
 	}
 
+	Py_INCREF(converters);
 	p->converters = converters;
+	Py_INCREF(callable);
 	p->callable = callable;
 	return p;
 
   error:
-	if (p) {
-		if (p->pcl)
-			FreeClosure(p->pcl);
-		PyMem_Free(p);
-	}
+	Py_XDECREF(p);
 	return NULL;
 }