mirror of https://github.com/python/cpython
Issue #2616: Implement ctypes.pointer() and ctypes.POINTER() in C for
better performance.
This commit is contained in:
parent
da950eb01c
commit
046e6a43ff
|
@ -242,27 +242,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
|
||||
|
@ -312,10 +292,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
|
||||
|
|
|
@ -29,6 +29,9 @@ Extensions Modules
|
|||
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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue