1414from _ctypes import RTLD_LOCAL , RTLD_GLOBAL
1515from _ctypes import ArgumentError
1616from _ctypes import SIZEOF_TIME_T
17+ from _ctypes import CField
1718
1819from struct import calcsize as _calcsize
1920
2021if __version__ != _ctypes_version :
2122 raise Exception ("Version number mismatch" , __version__ , _ctypes_version )
2223
2324if _os .name == "nt" :
24- from _ctypes import FormatError
25+ from _ctypes import COMError , CopyComPointer , FormatError
2526
2627DEFAULT_MODE = RTLD_LOCAL
2728if _os .name == "posix" and _sys .platform == "darwin" :
@@ -208,6 +209,18 @@ class c_longdouble(_SimpleCData):
208209if sizeof (c_longdouble ) == sizeof (c_double ):
209210 c_longdouble = c_double
210211
212+ try :
213+ class c_double_complex (_SimpleCData ):
214+ _type_ = "D"
215+ _check_size (c_double_complex )
216+ class c_float_complex (_SimpleCData ):
217+ _type_ = "F"
218+ _check_size (c_float_complex )
219+ class c_longdouble_complex (_SimpleCData ):
220+ _type_ = "G"
221+ except AttributeError :
222+ pass
223+
211224if _calcsize ("l" ) == _calcsize ("q" ):
212225 # if long and long long have the same size, make c_longlong an alias for c_long
213226 c_longlong = c_long
@@ -255,7 +268,72 @@ class c_void_p(_SimpleCData):
255268class c_bool (_SimpleCData ):
256269 _type_ = "?"
257270
258- from _ctypes import POINTER , pointer , _pointer_type_cache
271+ def POINTER (cls ):
272+ """Create and return a new ctypes pointer type.
273+
274+ Pointer types are cached and reused internally,
275+ so calling this function repeatedly is cheap.
276+ """
277+ if cls is None :
278+ return c_void_p
279+ try :
280+ return cls .__pointer_type__
281+ except AttributeError :
282+ pass
283+ if isinstance (cls , str ):
284+ # handle old-style incomplete types (see test_ctypes.test_incomplete)
285+ import warnings
286+ warnings ._deprecated ("ctypes.POINTER with string" , remove = (3 , 19 ))
287+ try :
288+ return _pointer_type_cache_fallback [cls ]
289+ except KeyError :
290+ result = type (f'LP_{ cls } ' , (_Pointer ,), {})
291+ _pointer_type_cache_fallback [cls ] = result
292+ return result
293+
294+ # create pointer type and set __pointer_type__ for cls
295+ return type (f'LP_{ cls .__name__ } ' , (_Pointer ,), {'_type_' : cls })
296+
297+ def pointer (obj ):
298+ """Create a new pointer instance, pointing to 'obj'.
299+
300+ The returned object is of the type POINTER(type(obj)). Note that if you
301+ just want to pass a pointer to an object to a foreign function call, you
302+ should use byref(obj) which is much faster.
303+ """
304+ typ = POINTER (type (obj ))
305+ return typ (obj )
306+
307+ class _PointerTypeCache :
308+ def __setitem__ (self , cls , pointer_type ):
309+ import warnings
310+ warnings ._deprecated ("ctypes._pointer_type_cache" , remove = (3 , 19 ))
311+ try :
312+ cls .__pointer_type__ = pointer_type
313+ except AttributeError :
314+ _pointer_type_cache_fallback [cls ] = pointer_type
315+
316+ def __getitem__ (self , cls ):
317+ import warnings
318+ warnings ._deprecated ("ctypes._pointer_type_cache" , remove = (3 , 19 ))
319+ try :
320+ return cls .__pointer_type__
321+ except AttributeError :
322+ return _pointer_type_cache_fallback [cls ]
323+
324+ def get (self , cls , default = None ):
325+ import warnings
326+ warnings ._deprecated ("ctypes._pointer_type_cache" , remove = (3 , 19 ))
327+ try :
328+ return cls .__pointer_type__
329+ except AttributeError :
330+ return _pointer_type_cache_fallback .get (cls , default )
331+
332+ def __contains__ (self , cls ):
333+ return hasattr (cls , '__pointer_type__' )
334+
335+ _pointer_type_cache_fallback = {}
336+ _pointer_type_cache = _PointerTypeCache ()
259337
260338class c_wchar_p (_SimpleCData ):
261339 _type_ = "Z"
@@ -266,15 +344,14 @@ class c_wchar(_SimpleCData):
266344 _type_ = "u"
267345
268346def _reset_cache ():
269- _pointer_type_cache .clear ()
347+ _pointer_type_cache_fallback .clear ()
270348 _c_functype_cache .clear ()
271349 if _os .name == "nt" :
272350 _win_functype_cache .clear ()
273351 # _SimpleCData.c_wchar_p_from_param
274352 POINTER (c_wchar ).from_param = c_wchar_p .from_param
275353 # _SimpleCData.c_char_p_from_param
276354 POINTER (c_char ).from_param = c_char_p .from_param
277- _pointer_type_cache [None ] = c_void_p
278355
279356def create_unicode_buffer (init , size = None ):
280357 """create_unicode_buffer(aString) -> character array
@@ -308,13 +385,7 @@ def create_unicode_buffer(init, size=None):
308385def SetPointerType (pointer , cls ):
309386 import warnings
310387 warnings ._deprecated ("ctypes.SetPointerType" , remove = (3 , 15 ))
311- if _pointer_type_cache .get (cls , None ) is not None :
312- raise RuntimeError ("This type already exists in the cache" )
313- if id (pointer ) not in _pointer_type_cache :
314- raise RuntimeError ("What's this???" )
315388 pointer .set_type (cls )
316- _pointer_type_cache [cls ] = pointer
317- del _pointer_type_cache [id (pointer )]
318389
319390def ARRAY (typ , len ):
320391 return typ * len
@@ -521,6 +592,7 @@ def WinError(code=None, descr=None):
521592# functions
522593
523594from _ctypes import _memmove_addr , _memset_addr , _string_at_addr , _cast_addr
595+ from _ctypes import _memoryview_at_addr
524596
525597## void *memmove(void *, const void *, size_t);
526598memmove = CFUNCTYPE (c_void_p , c_void_p , c_void_p , c_size_t )(_memmove_addr )
@@ -546,6 +618,14 @@ def string_at(ptr, size=-1):
546618 Return the byte string at void *ptr."""
547619 return _string_at (ptr , size )
548620
621+ _memoryview_at = PYFUNCTYPE (
622+ py_object , c_void_p , c_ssize_t , c_int )(_memoryview_at_addr )
623+ def memoryview_at (ptr , size , readonly = False ):
624+ """memoryview_at(ptr, size[, readonly]) -> memoryview
625+
626+ Return a memoryview representing the memory at void *ptr."""
627+ return _memoryview_at (ptr , size , bool (readonly ))
628+
549629try :
550630 from _ctypes import _wstring_at_addr
551631except ImportError :
0 commit comments