[Python-checkins] r62338 - in python/trunk: Lib/ctypes/__init__.py Misc/NEWS Modules/_ctypes/_ctypes.c Modules/_ctypes/callproc.c Modules/_ctypes/ctypes.h

thomas.heller python-checkins at python.org
Mon Apr 14 18:10:35 CEST 2008


Author: thomas.heller
Date: Mon Apr 14 18:10:07 2008
New Revision: 62338

Log:
Issue #2616: Implement ctypes.pointer() and ctypes.POINTER() in C for
better performance.


Modified:
   python/trunk/Lib/ctypes/__init__.py
   python/trunk/Misc/NEWS
   python/trunk/Modules/_ctypes/_ctypes.c
   python/trunk/Modules/_ctypes/callproc.c
   python/trunk/Modules/_ctypes/ctypes.h

Modified: python/trunk/Lib/ctypes/__init__.py
==============================================================================
--- python/trunk/Lib/ctypes/__init__.py	(original)
+++ python/trunk/Lib/ctypes/__init__.py	Mon Apr 14 18:10:07 2008
@@ -242,27 +242,7 @@
 class c_bool(_SimpleCData):
     _type_ = "?"
 
-# This cache maps types to pointers to them.
-_pointer_type_cache = {}
-
-def POINTER(cls):
-    try:
-        return _pointer_type_cache[cls]
-    except KeyError:
-        pass
-    if type(cls) is str:
-        klass = type(_Pointer)("LP_%s" % cls,
-                               (_Pointer,),
-                               {})
-        _pointer_type_cache[id(klass)] = klass
-        return klass
-    else:
-        name = "LP_%s" % cls.__name__
-        klass = type(_Pointer)(name,
-                               (_Pointer,),
-                               {'_type_': cls})
-        _pointer_type_cache[cls] = klass
-    return klass
+from _ctypes import POINTER, pointer, _pointer_type_cache
 
 try:
     from _ctypes import set_conversion_mode
@@ -312,10 +292,6 @@
     _pointer_type_cache[cls] = pointer
     del _pointer_type_cache[id(pointer)]
 
-
-def pointer(inst):
-    return POINTER(type(inst))(inst)
-
 # XXX Deprecated
 def ARRAY(typ, len):
     return typ * len

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Mon Apr 14 18:10:07 2008
@@ -29,6 +29,9 @@
 Library
 -------
 
+- Issue #2616: The ctypes.pointer() and ctypes.POINTER() functions are
+  now implemented in C for better performance.
+
 - Issue #2408: The ``_types`` module, which was used as in implementation
   detail of the public ``types`` module, has been removed and replaced by pure
   python code.

Modified: python/trunk/Modules/_ctypes/_ctypes.c
==============================================================================
--- python/trunk/Modules/_ctypes/_ctypes.c	(original)
+++ python/trunk/Modules/_ctypes/_ctypes.c	Mon Apr 14 18:10:07 2008
@@ -128,6 +128,10 @@
 #include "ctypes.h"
 
 PyObject *PyExc_ArgError;
+
+/* This dict maps ctypes types to POINTER types */
+PyObject *_pointer_type_cache;
+
 static PyTypeObject Simple_Type;
 
 /* a callable object used for unpickling */
@@ -5169,6 +5173,12 @@
 	if (!m)
 		return;
 
+	_pointer_type_cache = PyDict_New();
+	if (_pointer_type_cache == NULL)
+		return;
+
+	PyModule_AddObject(m, "_pointer_type_cache", (PyObject *)_pointer_type_cache);
+
 	_unpickle = PyObject_GetAttrString(m, "_unpickle");
 	if (_unpickle == NULL)
 		return;

Modified: python/trunk/Modules/_ctypes/callproc.c
==============================================================================
--- python/trunk/Modules/_ctypes/callproc.c	(original)
+++ python/trunk/Modules/_ctypes/callproc.c	Mon Apr 14 18:10:07 2008
@@ -1600,7 +1600,75 @@
 	return result;
 }
 
+static PyObject *
+POINTER(PyObject *self, PyObject *cls)
+{
+	PyObject *result;
+	PyTypeObject *typ;
+	PyObject *key;
+	char *buf;
+
+	result = PyDict_GetItem(_pointer_type_cache, cls);
+	if (result) {
+		Py_INCREF(result);
+		return result;
+	}
+	if (PyString_CheckExact(cls)) {
+		buf = alloca(strlen(PyString_AS_STRING(cls)) + 3 + 1);
+		sprintf(buf, "LP_%s", PyString_AS_STRING(cls));
+		result = PyObject_CallFunction((PyObject *)Py_TYPE(&Pointer_Type),
+					       "s(O){}",
+					       buf,
+					       &Pointer_Type);
+		if (result == NULL)
+			return result;
+		key = PyLong_FromVoidPtr(result);
+	} else if (PyType_Check(cls)) {
+		typ = (PyTypeObject *)cls;
+		buf = alloca(strlen(typ->tp_name) + 3 + 1);
+		sprintf(buf, "LP_%s", typ->tp_name);
+		result = PyObject_CallFunction((PyObject *)Py_TYPE(&Pointer_Type),
+					       "s(O){sO}",
+					       buf,
+					       &Pointer_Type,
+					       "_type_", cls);
+		if (result == NULL)
+			return result;
+		Py_INCREF(cls);
+		key = cls;
+	} else {
+		PyErr_SetString(PyExc_TypeError, "must be a ctypes type");
+		return NULL;
+	}
+	if (-1 == PyDict_SetItem(_pointer_type_cache, key, result)) {
+		Py_DECREF(result);
+		Py_DECREF(key);
+		return NULL;
+	}
+	Py_DECREF(key);
+	return result;
+}
+
+static PyObject *
+pointer(PyObject *self, PyObject *arg)
+{
+	PyObject *result;
+	PyObject *typ;
+
+	typ = PyDict_GetItem(_pointer_type_cache, (PyObject *)Py_TYPE(arg));
+	if (typ)
+		return PyObject_CallFunctionObjArgs(typ, arg, NULL);
+	typ = POINTER(NULL, (PyObject *)Py_TYPE(arg));
+	if (typ == NULL)
+			return NULL;
+	result = PyObject_CallFunctionObjArgs(typ, arg, NULL);
+	Py_DECREF(typ);
+	return result;
+}
+
 PyMethodDef module_methods[] = {
+	{"POINTER", POINTER, METH_O },
+	{"pointer", pointer, METH_O },
 	{"_unpickle", unpickle, METH_VARARGS },
 	{"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"},
 #ifdef CTYPES_UNICODE

Modified: python/trunk/Modules/_ctypes/ctypes.h
==============================================================================
--- python/trunk/Modules/_ctypes/ctypes.h	(original)
+++ python/trunk/Modules/_ctypes/ctypes.h	Mon Apr 14 18:10:07 2008
@@ -415,6 +415,7 @@
 /* XXX better name needed! */
 extern int IsSimpleSubType(PyObject *obj);
 
+extern PyObject *_pointer_type_cache;
 
 #ifdef MS_WIN32
 extern PyObject *ComError;


More information about the Python-checkins mailing list