mirror of
https://github.com/python/cpython.git
synced 2025-11-25 12:44:13 +00:00
Issue #2616: Implement ctypes.pointer() and ctypes.POINTER() in C for
better performance.
This commit is contained in:
parent
da950eb01c
commit
046e6a43ff
5 changed files with 83 additions and 25 deletions
|
|
@ -242,27 +242,7 @@ _check_size(c_void_p)
|
||||||
class c_bool(_SimpleCData):
|
class c_bool(_SimpleCData):
|
||||||
_type_ = "?"
|
_type_ = "?"
|
||||||
|
|
||||||
# This cache maps types to pointers to them.
|
from _ctypes import POINTER, pointer, _pointer_type_cache
|
||||||
_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
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from _ctypes import set_conversion_mode
|
from _ctypes import set_conversion_mode
|
||||||
|
|
@ -312,10 +292,6 @@ def SetPointerType(pointer, cls):
|
||||||
_pointer_type_cache[cls] = pointer
|
_pointer_type_cache[cls] = pointer
|
||||||
del _pointer_type_cache[id(pointer)]
|
del _pointer_type_cache[id(pointer)]
|
||||||
|
|
||||||
|
|
||||||
def pointer(inst):
|
|
||||||
return POINTER(type(inst))(inst)
|
|
||||||
|
|
||||||
# XXX Deprecated
|
# XXX Deprecated
|
||||||
def ARRAY(typ, len):
|
def ARRAY(typ, len):
|
||||||
return typ * len
|
return typ * len
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ Extensions Modules
|
||||||
Library
|
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
|
- Issue #2408: The ``_types`` module, which was used as in implementation
|
||||||
detail of the public ``types`` module, has been removed and replaced by pure
|
detail of the public ``types`` module, has been removed and replaced by pure
|
||||||
python code.
|
python code.
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,10 @@ bytes(cdata)
|
||||||
#include "ctypes.h"
|
#include "ctypes.h"
|
||||||
|
|
||||||
PyObject *PyExc_ArgError;
|
PyObject *PyExc_ArgError;
|
||||||
|
|
||||||
|
/* This dict maps ctypes types to POINTER types */
|
||||||
|
PyObject *_pointer_type_cache;
|
||||||
|
|
||||||
static PyTypeObject Simple_Type;
|
static PyTypeObject Simple_Type;
|
||||||
|
|
||||||
/* a callable object used for unpickling */
|
/* a callable object used for unpickling */
|
||||||
|
|
@ -5169,6 +5173,12 @@ init_ctypes(void)
|
||||||
if (!m)
|
if (!m)
|
||||||
return;
|
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");
|
_unpickle = PyObject_GetAttrString(m, "_unpickle");
|
||||||
if (_unpickle == NULL)
|
if (_unpickle == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1600,7 +1600,75 @@ unpickle(PyObject *self, PyObject *args)
|
||||||
return result;
|
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[] = {
|
PyMethodDef module_methods[] = {
|
||||||
|
{"POINTER", POINTER, METH_O },
|
||||||
|
{"pointer", pointer, METH_O },
|
||||||
{"_unpickle", unpickle, METH_VARARGS },
|
{"_unpickle", unpickle, METH_VARARGS },
|
||||||
{"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"},
|
{"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"},
|
||||||
#ifdef CTYPES_UNICODE
|
#ifdef CTYPES_UNICODE
|
||||||
|
|
|
||||||
|
|
@ -415,6 +415,7 @@ extern PyObject *CData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t in
|
||||||
/* XXX better name needed! */
|
/* XXX better name needed! */
|
||||||
extern int IsSimpleSubType(PyObject *obj);
|
extern int IsSimpleSubType(PyObject *obj);
|
||||||
|
|
||||||
|
extern PyObject *_pointer_type_cache;
|
||||||
|
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
extern PyObject *ComError;
|
extern PyObject *ComError;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue