From 3071f8191bec3fee4a9fc5f8ec30c52dc8cd3ac2 Mon Sep 17 00:00:00 2001 From: Thomas Heller Date: Mon, 14 Apr 2008 16:17:33 +0000 Subject: Merged revisions 62338 via svnmerge from 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 | 26 +---------------- Modules/_ctypes/_ctypes.c | 10 +++++++ Modules/_ctypes/callproc.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ Modules/_ctypes/ctypes.h | 1 + 4 files changed, 81 insertions(+), 25 deletions(-) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index b6e598f..abda3df 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -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 diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 6f06270..381d801 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -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; diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 8656569..2e8635a 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -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 diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 0e77999..1390daf 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -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; -- cgit v0.12