@@ -266,7 +266,72 @@ class c_void_p(_SimpleCData):
266266class c_bool (_SimpleCData ):
267267 _type_ = "?"
268268
269- from _ctypes import POINTER , pointer , _pointer_type_cache
269+ def POINTER (cls ):
270+ """Create and return a new ctypes pointer type.
271+
272+ Pointer types are cached and reused internally,
273+ so calling this function repeatedly is cheap.
274+ """
275+ if cls is None :
276+ return c_void_p
277+ try :
278+ return cls .__pointer_type__
279+ except AttributeError :
280+ pass
281+ if isinstance (cls , str ):
282+ # handle old-style incomplete types (see test_ctypes.test_incomplete)
283+ import warnings
284+ warnings ._deprecated ("ctypes.POINTER with string" , remove = (3 , 19 ))
285+ try :
286+ return _pointer_type_cache_fallback [cls ]
287+ except KeyError :
288+ result = type (f'LP_{ cls } ' , (_Pointer ,), {})
289+ _pointer_type_cache_fallback [cls ] = result
290+ return result
291+
292+ # create pointer type and set __pointer_type__ for cls
293+ return type (f'LP_{ cls .__name__ } ' , (_Pointer ,), {'_type_' : cls })
294+
295+ def pointer (obj ):
296+ """Create a new pointer instance, pointing to 'obj'.
297+
298+ The returned object is of the type POINTER(type(obj)). Note that if you
299+ just want to pass a pointer to an object to a foreign function call, you
300+ should use byref(obj) which is much faster.
301+ """
302+ typ = POINTER (type (obj ))
303+ return typ (obj )
304+
305+ class _PointerTypeCache :
306+ def __setitem__ (self , cls , pointer_type ):
307+ import warnings
308+ warnings ._deprecated ("ctypes._pointer_type_cache" , remove = (3 , 19 ))
309+ try :
310+ cls .__pointer_type__ = pointer_type
311+ except AttributeError :
312+ _pointer_type_cache_fallback [cls ] = pointer_type
313+
314+ def __getitem__ (self , cls ):
315+ import warnings
316+ warnings ._deprecated ("ctypes._pointer_type_cache" , remove = (3 , 19 ))
317+ try :
318+ return cls .__pointer_type__
319+ except AttributeError :
320+ return _pointer_type_cache_fallback [cls ]
321+
322+ def get (self , cls , default = None ):
323+ import warnings
324+ warnings ._deprecated ("ctypes._pointer_type_cache" , remove = (3 , 19 ))
325+ try :
326+ return cls .__pointer_type__
327+ except AttributeError :
328+ return _pointer_type_cache_fallback .get (cls , default )
329+
330+ def __contains__ (self , cls ):
331+ return hasattr (cls , '__pointer_type__' )
332+
333+ _pointer_type_cache_fallback = {}
334+ _pointer_type_cache = _PointerTypeCache ()
270335
271336class c_wchar_p (_SimpleCData ):
272337 _type_ = "Z"
@@ -277,15 +342,14 @@ class c_wchar(_SimpleCData):
277342 _type_ = "u"
278343
279344def _reset_cache ():
280- _pointer_type_cache .clear ()
345+ _pointer_type_cache_fallback .clear ()
281346 _c_functype_cache .clear ()
282347 if _os .name == "nt" :
283348 _win_functype_cache .clear ()
284349 # _SimpleCData.c_wchar_p_from_param
285350 POINTER (c_wchar ).from_param = c_wchar_p .from_param
286351 # _SimpleCData.c_char_p_from_param
287352 POINTER (c_char ).from_param = c_char_p .from_param
288- _pointer_type_cache [None ] = c_void_p
289353
290354def create_unicode_buffer (init , size = None ):
291355 """create_unicode_buffer(aString) -> character array
@@ -319,13 +383,7 @@ def create_unicode_buffer(init, size=None):
319383def SetPointerType (pointer , cls ):
320384 import warnings
321385 warnings ._deprecated ("ctypes.SetPointerType" , remove = (3 , 15 ))
322- if _pointer_type_cache .get (cls , None ) is not None :
323- raise RuntimeError ("This type already exists in the cache" )
324- if id (pointer ) not in _pointer_type_cache :
325- raise RuntimeError ("What's this???" )
326386 pointer .set_type (cls )
327- _pointer_type_cache [cls ] = pointer
328- del _pointer_type_cache [id (pointer )]
329387
330388def ARRAY (typ , len ):
331389 return typ * len
0 commit comments