summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorThomas Heller <theller@ctypes.org>2008-04-14 16:10:07 (GMT)
committerThomas Heller <theller@ctypes.org>2008-04-14 16:10:07 (GMT)
commit046e6a43ff64885d9f5cdaac13a2b9f6e0ee8c84 (patch)
tree5acb0a36e8bcadbf5bca7c981c911178af2acbe6 /Modules
parentda950eb01c1191e6ccdd02ca009fca7ead2b3066 (diff)
downloadcpython-046e6a43ff64885d9f5cdaac13a2b9f6e0ee8c84.zip
cpython-046e6a43ff64885d9f5cdaac13a2b9f6e0ee8c84.tar.gz
cpython-046e6a43ff64885d9f5cdaac13a2b9f6e0ee8c84.tar.bz2
Issue #2616: Implement ctypes.pointer() and ctypes.POINTER() in C for
better performance.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_ctypes/_ctypes.c10
-rw-r--r--Modules/_ctypes/callproc.c68
-rw-r--r--Modules/_ctypes/ctypes.h1
3 files changed, 79 insertions, 0 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index b23c3d8..355fda2 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -128,6 +128,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 */
@@ -5169,6 +5173,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 783df08..c528179 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -1600,7 +1600,75 @@ 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 (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
diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h
index d0e7814..8f6846a 100644
--- a/Modules/_ctypes/ctypes.h
+++ b/Modules/_ctypes/ctypes.h
@@ -415,6 +415,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;