]> granicus.if.org Git - python/commitdiff
Merged revisions 62338 via svnmerge from
authorThomas Heller <theller@ctypes.org>
Mon, 14 Apr 2008 16:17:33 +0000 (16:17 +0000)
committerThomas Heller <theller@ctypes.org>
Mon, 14 Apr 2008 16:17:33 +0000 (16:17 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r62338 | thomas.heller | 2008-04-14 18:10:07 +0200 (Mo, 14 Apr 2008) | 3 lines

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

Lib/ctypes/__init__.py
Modules/_ctypes/_ctypes.c
Modules/_ctypes/callproc.c
Modules/_ctypes/ctypes.h

index b6e598ffedd6a631f78c4c9ddd7dc2deb180f932..abda3dfcbef91e84010dd4c141a111e69f5e5ccb 100644 (file)
@@ -239,27 +239,7 @@ _check_size(c_void_p)
 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
@@ -309,10 +289,6 @@ def SetPointerType(pointer, cls):
     _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
index 6f062703a1abc4480c7a33442d358d4c56759cf3..381d8018679ff60d87d466af478701940b2a8d43 100644 (file)
@@ -123,6 +123,10 @@ bytes(cdata)
 #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 */
@@ -4994,6 +4998,12 @@ init_ctypes(void)
        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;
index 8656569cfc3b6ad8dbb71018d8af263816376b29..2e8635a87bf83d5026bf8f040fe3b69673d6d5ee 100644 (file)
@@ -1565,7 +1565,76 @@ unpickle(PyObject *self, PyObject *args)
        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 (PyUnicode_CheckExact(cls)) {
+               char *name = PyUnicode_AsString(cls);
+               buf = alloca(strlen(name) + 3 + 1);
+               sprintf(buf, "LP_%s", name);
+               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
index 0e7799983f4efa0ac2e4f9173407c5d38c3a1730..1390daf846991e626df5d1f8eb195de1e529849c 100644 (file)
@@ -342,6 +342,7 @@ extern PyObject *CData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t in
 /* XXX better name needed! */
 extern int IsSimpleSubType(PyObject *obj);
 
+extern PyObject *_pointer_type_cache;
 
 #ifdef MS_WIN32
 extern PyObject *ComError;