Skip to content

Commit 3071f81

Browse files
author
Thomas Heller
committed
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 python#2616: Implement ctypes.pointer() and ctypes.POINTER() in C for better performance. ........
1 parent c2ea8c6 commit 3071f81

File tree

4 files changed

+81
-25
lines changed

4 files changed

+81
-25
lines changed

Lib/ctypes/__init__.py

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -239,27 +239,7 @@ class c_void_p(_SimpleCData):
239239
class c_bool(_SimpleCData):
240240
_type_ = "?"
241241

242-
# This cache maps types to pointers to them.
243-
_pointer_type_cache = {}
244-
245-
def POINTER(cls):
246-
try:
247-
return _pointer_type_cache[cls]
248-
except KeyError:
249-
pass
250-
if type(cls) is str:
251-
klass = type(_Pointer)("LP_%s" % cls,
252-
(_Pointer,),
253-
{})
254-
_pointer_type_cache[id(klass)] = klass
255-
return klass
256-
else:
257-
name = "LP_%s" % cls.__name__
258-
klass = type(_Pointer)(name,
259-
(_Pointer,),
260-
{'_type_': cls})
261-
_pointer_type_cache[cls] = klass
262-
return klass
242+
from _ctypes import POINTER, pointer, _pointer_type_cache
263243

264244
try:
265245
from _ctypes import set_conversion_mode
@@ -309,10 +289,6 @@ def SetPointerType(pointer, cls):
309289
_pointer_type_cache[cls] = pointer
310290
del _pointer_type_cache[id(pointer)]
311291

312-
313-
def pointer(inst):
314-
return POINTER(type(inst))(inst)
315-
316292
# XXX Deprecated
317293
def ARRAY(typ, len):
318294
return typ * len

Modules/_ctypes/_ctypes.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ bytes(cdata)
123123
#include "ctypes.h"
124124

125125
PyObject *PyExc_ArgError;
126+
127+
/* This dict maps ctypes types to POINTER types */
128+
PyObject *_pointer_type_cache;
129+
126130
static PyTypeObject Simple_Type;
127131

128132
/* a callable object used for unpickling */
@@ -4994,6 +4998,12 @@ init_ctypes(void)
49944998
if (!m)
49954999
return;
49965000

5001+
_pointer_type_cache = PyDict_New();
5002+
if (_pointer_type_cache == NULL)
5003+
return;
5004+
5005+
PyModule_AddObject(m, "_pointer_type_cache", (PyObject *)_pointer_type_cache);
5006+
49975007
_unpickle = PyObject_GetAttrString(m, "_unpickle");
49985008
if (_unpickle == NULL)
49995009
return;

Modules/_ctypes/callproc.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,7 +1565,76 @@ unpickle(PyObject *self, PyObject *args)
15651565
return result;
15661566
}
15671567

1568+
static PyObject *
1569+
POINTER(PyObject *self, PyObject *cls)
1570+
{
1571+
PyObject *result;
1572+
PyTypeObject *typ;
1573+
PyObject *key;
1574+
char *buf;
1575+
1576+
result = PyDict_GetItem(_pointer_type_cache, cls);
1577+
if (result) {
1578+
Py_INCREF(result);
1579+
return result;
1580+
}
1581+
if (PyUnicode_CheckExact(cls)) {
1582+
char *name = PyUnicode_AsString(cls);
1583+
buf = alloca(strlen(name) + 3 + 1);
1584+
sprintf(buf, "LP_%s", name);
1585+
result = PyObject_CallFunction((PyObject *)Py_TYPE(&Pointer_Type),
1586+
"s(O){}",
1587+
buf,
1588+
&Pointer_Type);
1589+
if (result == NULL)
1590+
return result;
1591+
key = PyLong_FromVoidPtr(result);
1592+
} else if (PyType_Check(cls)) {
1593+
typ = (PyTypeObject *)cls;
1594+
buf = alloca(strlen(typ->tp_name) + 3 + 1);
1595+
sprintf(buf, "LP_%s", typ->tp_name);
1596+
result = PyObject_CallFunction((PyObject *)Py_TYPE(&Pointer_Type),
1597+
"s(O){sO}",
1598+
buf,
1599+
&Pointer_Type,
1600+
"_type_", cls);
1601+
if (result == NULL)
1602+
return result;
1603+
Py_INCREF(cls);
1604+
key = cls;
1605+
} else {
1606+
PyErr_SetString(PyExc_TypeError, "must be a ctypes type");
1607+
return NULL;
1608+
}
1609+
if (-1 == PyDict_SetItem(_pointer_type_cache, key, result)) {
1610+
Py_DECREF(result);
1611+
Py_DECREF(key);
1612+
return NULL;
1613+
}
1614+
Py_DECREF(key);
1615+
return result;
1616+
}
1617+
1618+
static PyObject *
1619+
pointer(PyObject *self, PyObject *arg)
1620+
{
1621+
PyObject *result;
1622+
PyObject *typ;
1623+
1624+
typ = PyDict_GetItem(_pointer_type_cache, (PyObject *)Py_TYPE(arg));
1625+
if (typ)
1626+
return PyObject_CallFunctionObjArgs(typ, arg, NULL);
1627+
typ = POINTER(NULL, (PyObject *)Py_TYPE(arg));
1628+
if (typ == NULL)
1629+
return NULL;
1630+
result = PyObject_CallFunctionObjArgs(typ, arg, NULL);
1631+
Py_DECREF(typ);
1632+
return result;
1633+
}
1634+
15681635
PyMethodDef module_methods[] = {
1636+
{"POINTER", POINTER, METH_O },
1637+
{"pointer", pointer, METH_O },
15691638
{"_unpickle", unpickle, METH_VARARGS },
15701639
{"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"},
15711640
#ifdef CTYPES_UNICODE

Modules/_ctypes/ctypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ extern PyObject *CData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t in
342342
/* XXX better name needed! */
343343
extern int IsSimpleSubType(PyObject *obj);
344344

345+
extern PyObject *_pointer_type_cache;
345346

346347
#ifdef MS_WIN32
347348
extern PyObject *ComError;

0 commit comments

Comments
 (0)