8000 Move ctype's pointers cache to StgInfo · python/cpython@87a974b · GitHub
[go: up one dir, main page]

Skip to content

Commit 87a974b

Browse files
Move ctype's pointers cache to StgInfo
1 parent 55815a6 commit 87a974b

File tree

9 files changed

+23
-38
lines changed

9 files changed

+23
-38
lines changed

Lib/ctypes/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,9 @@ def SetPointerType(pointer, cls):
319319
warnings._deprecated("ctypes.SetPointerType", remove=(3, 15))
320320
if _pointer_type_cache.get(cls, None) is not None:
321321
raise RuntimeError("This type already exists in the cache")
322-
if id(pointer) not in _pointer_type_cache:
323-
raise RuntimeError("What's this???")
322+
324323
pointer.set_type(cls)
325324
_pointer_type_cache[cls] = pointer
326-
del _pointer_type_cache[id(pointer)]
327325

328326
def ARRAY(typ, len):
329327
return typ * len

Lib/test/test_ctypes/test_byteswap.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ class TestStructure(parent):
226226
self.assertEqual(len(data), sizeof(TestStructure))
227227
ptr = POINTER(TestStructure)
228228
s = cast(data, ptr)[0]
229-
del ctypes._pointer_type_cache[TestStructure]
230229
self.assertEqual(s.point.x, 1)
231230
self.assertEqual(s.point.y, 2)
232231

@@ -359,7 +358,6 @@ class TestUnion(parent):
359358
self.assertEqual(len(data), sizeof(TestUnion))
360359
ptr = POINTER(TestUnion)
361360
s = cast(data, ptr)[0]
362-
del ctypes._pointer_type_cache[TestUnion]
363361
self.assertEqual(s.point.x, 1)
364362
self.assertEqual(s.point.y, 2)
365363

Lib/test/test_ctypes/test_keeprefs.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import unittest
2-
from ctypes import (Structure, POINTER, pointer, _pointer_type_cache,
3-
c_char_p, c_int)
2+
from ctypes import (Structure, POINTER, pointer, c_char_p, c_int)
43

54

65
class SimpleTestCase(unittest.TestCase):
@@ -115,10 +114,6 @@ class RECT(Structure):
115114
r.a[0].x = 42
116115
r.a[0].y = 99
117116

118-
# to avoid leaking when tests are run several times
119-
# clean up the types left in the cache.
120-
del _pointer_type_cache[POINT]
121-
122117

123118
if __name__ == "__main__":
124119
unittest.main()

Lib/test/test_ctypes/test_pointers.py

Lines changed: 1 addition & 9 deletions
F438
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import sys
44
import unittest
55
from ctypes import (CDLL, CFUNCTYPE, Structure,
6-
POINTER, pointer, _Pointer, _pointer_type_cache,
6+
POINTER, pointer, _Pointer,
77
byref, sizeof,
88
c_void_p, c_char_p,
99
c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
@@ -141,8 +141,6 @@ class Table(Structure):
141141

142142
pt.contents.c = 33
143143

144-
del _pointer_type_cache[Table]
145-
146144
def test_basic(self):
147145
p = pointer(c_int(42))
148146
# Although a pointer can be indexed, it has no length
@@ -210,17 +208,11 @@ def test_pointer_type_name(self):
210208
LargeNamedType = type('T' * 2 ** 25, (Structure,), {})
211209
self.assertTrue(POINTER(LargeNamedType))
212210

213-
# to not leak references, we must clean _pointer_type_cache
214-
del _pointer_type_cache[LargeNamedType]
215-
216211
def test_pointer_type_str_name(self):
217212
large_string = 'T' * 2 ** 25
218213
P = POINTER(large_string)
219214
self.assertTrue(P)
220215

221-
# to not leak references, we must clean _pointer_type_cache
222-
del _pointer_type_cache[id(P)]
223-
224216
def test_abstract(self):
225217
self.assertRaises(TypeError, _Pointer.set_type, 42)
226218

Lib/test/test_ctypes/test_values.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import sys
88
import unittest
99
from ctypes import (Structure, CDLL, POINTER, pythonapi,
10-
_pointer_type_cache,
1110
c_ubyte, c_char_p, c_int)
1211
from test.support import import_helper
1312

@@ -96,8 +95,6 @@ class struct_frozen(Structure):
9695
"_PyImport_FrozenBootstrap example "
9796
"in Doc/library/ctypes.rst may be out of date")
9897

99-
del _pointer_type_cache[struct_frozen]
100-
10198
def test_undefined(self):
10299
self.assertRaises(ValueError, c_int.in_dll, pythonapi,
103100
"Undefined_Symbol")

Lib/test/test_ctypes/test_win32.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import sys
66
import unittest
77
from ctypes import (CDLL, Structure, POINTER, pointer, sizeof, byref,
8-
_pointer_type_cache,
98
c_void_p, c_char, c_int, c_long)
109
from test import support
1110
from test.support import import_helper
@@ -145,8 +144,8 @@ class RECT(Structure):
145144
self.assertEqual(ret.top, top.value)
146145
self.assertEqual(ret.bottom, bottom.value)
147146

148-
# to not leak references, we must clean _pointer_type_cache
149-
del _pointer_type_cache[RECT]
147+
self.assertEqual(id(PointInRect.argtypes[0]), id(ReturnRect.argtypes[2]))
148+
self.assertEqual(id(PointInRect.argtypes[0]), id(ReturnRect.argtypes[5]))
150149

151150

152151
if __name__ == '__main__':

Modules/_ctypes/_ctypes.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ CType_Type_traverse(PyObject *self, visitproc visit, void *arg)
474474
Py_VISIT(info->restype);
475475
Py_VISIT(info->checker);
476476
Py_VISIT(info->module);
477+
Py_VISIT(info->pointer_type);
477478
}
478479
Py_VISIT(Py_TYPE(self));
479480
return PyType_Type.tp_traverse(self, visit, arg);
@@ -489,6 +490,7 @@ ctype_clear_stginfo(StgInfo *info)
489490
Py_CLEAR(info->restype);
490491
Py_CLEAR(info->checker);
491492
Py_CLEAR(info->module);
493+
Py_CLEAR(info->pointer_type);
492494
}
493495

494496
static int

Modules/_ctypes/callproc.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,14 +1990,23 @@ create_pointer_type(PyObject *module, PyObject *cls)
19901990
{
19911991
PyObject *result;
19921992
PyTypeObject *typ;
1993-
PyObject *key;
19941993

19951994
assert(module);
19961995
ctypes_state *st = get_module_state(module);
19971996
if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, cls, &result) != 0) {
19981997
// found or error
19991998
return result;
20001999
}
2000+
2001+
StgInfo* info = NULL;
2002+
if (PyStgInfo_FromAny(st, cls, &info) < 0) {
2003+
return NULL;
2004+
}
2005+
2006+
if (info && info->pointer_type) {
2007+
return Py_XNewRef(info->pointer_type);
2008+
}
2009+
20012010
// not found
20022011
if (PyUnicode_CheckExact(cls)) {
20032012
PyObject *name = PyUnicode_FromFormat("LP_%U", cls);
@@ -2007,11 +2016,6 @@ create_pointer_type(PyObject *module, PyObject *cls)
20072016
st->PyCPointer_Type);
20082017
if (result == NULL)
20092018
return result;
2010-
key = PyLong_FromVoidPtr(result);
2011-
if (key == NULL) {
2012-
Py_DECREF(result);
2013-
return NULL;
2014-
}
20152019
} else if (PyType_Check(cls)) {
20162020
typ = (PyTypeObject *)cls;
20172021
PyObject *name = PyUnicode_FromFormat("LP_%s", typ->tp_name);
@@ -2022,17 +2026,15 @@ create_pointer_type(PyObject *module, PyObject *cls)
20222026
"_type_", cls);
20232027
if (result == NULL)
20242028
return result;
2025-
key = Py_NewRef(cls);
20262029
} else {
20272030
PyErr_SetString(PyExc_TypeError, "must be a ctypes type");
20282031
return NULL;
20292032
}
2030-
if (PyDict_SetItem(st->_ctypes_ptrtype_cache, key, result) < 0) {
2031-
Py_DECREF(result);
2032-
Py_DECREF(key);
2033-
return NULL;
2033+
2034+
if (info) {
2035+
info->pointer_type = Py_XNewRef(result);
20342036
}
2035-
Py_DECREF(key);
2037+
20362038
return result;
20372039
}
20382040

Modules/_ctypes/ctypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ typedef struct {
373373
Py_ssize_t *shape;
374374
/* Py_ssize_t *strides; */ /* unused in ctypes */
375375
/* Py_ssize_t *suboffsets; */ /* unused in ctypes */
376+
PyObject *pointer_type;
376377
} StgInfo;
377378

378379
extern int PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info);
@@ -566,6 +567,7 @@ PyStgInfo_Init(ctypes_state *state, PyTypeObject *type)
566567
return NULL;
567568
}
568569
info->module = Py_NewRef(module);
570+
info->pointer_type = NULL;
569571

570572
info->initialized = 1;
571573
return info;

0 commit comments

Comments
 (0)
0