Coverage for /pythoncovmergedfiles/medio/medio/usr/lib/python3.9/ctypes/__init__.py: 1%
347 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1"""create and manipulate C data types in Python"""
3import os as _os, sys as _sys
4import types as _types
6__version__ = "1.1.0"
8from _ctypes import Union, Structure, Array
9from _ctypes import _Pointer
10from _ctypes import CFuncPtr as _CFuncPtr
11from _ctypes import __version__ as _ctypes_version
12from _ctypes import RTLD_LOCAL, RTLD_GLOBAL
13from _ctypes import ArgumentError
15from struct import calcsize as _calcsize
17if __version__ != _ctypes_version:
18 raise Exception("Version number mismatch", __version__, _ctypes_version)
20if _os.name == "nt":
21 from _ctypes import FormatError
23DEFAULT_MODE = RTLD_LOCAL
24if _os.name == "posix" and _sys.platform == "darwin":
25 # On OS X 10.3, we use RTLD_GLOBAL as default mode
26 # because RTLD_LOCAL does not work at least on some
27 # libraries. OS X 10.3 is Darwin 7, so we check for
28 # that.
30 if int(_os.uname().release.split('.')[0]) < 8:
31 DEFAULT_MODE = RTLD_GLOBAL
33from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \
34 FUNCFLAG_PYTHONAPI as _FUNCFLAG_PYTHONAPI, \
35 FUNCFLAG_USE_ERRNO as _FUNCFLAG_USE_ERRNO, \
36 FUNCFLAG_USE_LASTERROR as _FUNCFLAG_USE_LASTERROR
38# WINOLEAPI -> HRESULT
39# WINOLEAPI_(type)
40#
41# STDMETHODCALLTYPE
42#
43# STDMETHOD(name)
44# STDMETHOD_(type, name)
45#
46# STDAPICALLTYPE
48def create_string_buffer(init, size=None):
49 """create_string_buffer(aBytes) -> character array
50 create_string_buffer(anInteger) -> character array
51 create_string_buffer(aBytes, anInteger) -> character array
52 """
53 if isinstance(init, bytes):
54 if size is None:
55 size = len(init)+1
56 _sys.audit("ctypes.create_string_buffer", init, size)
57 buftype = c_char * size
58 buf = buftype()
59 buf.value = init
60 return buf
61 elif isinstance(init, int):
62 _sys.audit("ctypes.create_string_buffer", None, init)
63 buftype = c_char * init
64 buf = buftype()
65 return buf
66 raise TypeError(init)
68def c_buffer(init, size=None):
69## "deprecated, use create_string_buffer instead"
70## import warnings
71## warnings.warn("c_buffer is deprecated, use create_string_buffer instead",
72## DeprecationWarning, stacklevel=2)
73 return create_string_buffer(init, size)
75_c_functype_cache = {}
76def CFUNCTYPE(restype, *argtypes, **kw):
77 """CFUNCTYPE(restype, *argtypes,
78 use_errno=False, use_last_error=False) -> function prototype.
80 restype: the result type
81 argtypes: a sequence specifying the argument types
83 The function prototype can be called in different ways to create a
84 callable object:
86 prototype(integer address) -> foreign function
87 prototype(callable) -> create and return a C callable function from callable
88 prototype(integer index, method name[, paramflags]) -> foreign function calling a COM method
89 prototype((ordinal number, dll object)[, paramflags]) -> foreign function exported by ordinal
90 prototype((function name, dll object)[, paramflags]) -> foreign function exported by name
91 """
92 flags = _FUNCFLAG_CDECL
93 if kw.pop("use_errno", False):
94 flags |= _FUNCFLAG_USE_ERRNO
95 if kw.pop("use_last_error", False):
96 flags |= _FUNCFLAG_USE_LASTERROR
97 if kw:
98 raise ValueError("unexpected keyword argument(s) %s" % kw.keys())
99 try:
100 return _c_functype_cache[(restype, argtypes, flags)]
101 except KeyError:
102 class CFunctionType(_CFuncPtr):
103 _argtypes_ = argtypes
104 _restype_ = restype
105 _flags_ = flags
106 _c_functype_cache[(restype, argtypes, flags)] = CFunctionType
107 return CFunctionType
109if _os.name == "nt":
110 from _ctypes import LoadLibrary as _dlopen
111 from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL
113 _win_functype_cache = {}
114 def WINFUNCTYPE(restype, *argtypes, **kw):
115 # docstring set later (very similar to CFUNCTYPE.__doc__)
116 flags = _FUNCFLAG_STDCALL
117 if kw.pop("use_errno", False):
118 flags |= _FUNCFLAG_USE_ERRNO
119 if kw.pop("use_last_error", False):
120 flags |= _FUNCFLAG_USE_LASTERROR
121 if kw:
122 raise ValueError("unexpected keyword argument(s) %s" % kw.keys())
123 try:
124 return _win_functype_cache[(restype, argtypes, flags)]
125 except KeyError:
126 class WinFunctionType(_CFuncPtr):
127 _argtypes_ = argtypes
128 _restype_ = restype
129 _flags_ = flags
130 _win_functype_cache[(restype, argtypes, flags)] = WinFunctionType
131 return WinFunctionType
132 if WINFUNCTYPE.__doc__:
133 WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE")
135elif _os.name == "posix":
136 from _ctypes import dlopen as _dlopen
138from _ctypes import sizeof, byref, addressof, alignment, resize
139from _ctypes import get_errno, set_errno
140from _ctypes import _SimpleCData
142def _check_size(typ, typecode=None):
143 # Check if sizeof(ctypes_type) against struct.calcsize. This
144 # should protect somewhat against a misconfigured libffi.
145 from struct import calcsize
146 if typecode is None:
147 # Most _type_ codes are the same as used in struct
148 typecode = typ._type_
149 actual, required = sizeof(typ), calcsize(typecode)
150 if actual != required:
151 raise SystemError("sizeof(%s) wrong: %d instead of %d" % \
152 (typ, actual, required))
154class py_object(_SimpleCData):
155 _type_ = "O"
156 def __repr__(self):
157 try:
158 return super().__repr__()
159 except ValueError:
160 return "%s(<NULL>)" % type(self).__name__
161_check_size(py_object, "P")
163class c_short(_SimpleCData):
164 _type_ = "h"
165_check_size(c_short)
167class c_ushort(_SimpleCData):
168 _type_ = "H"
169_check_size(c_ushort)
171class c_long(_SimpleCData):
172 _type_ = "l"
173_check_size(c_long)
175class c_ulong(_SimpleCData):
176 _type_ = "L"
177_check_size(c_ulong)
179if _calcsize("i") == _calcsize("l"):
180 # if int and long have the same size, make c_int an alias for c_long
181 c_int = c_long
182 c_uint = c_ulong
183else:
184 class c_int(_SimpleCData):
185 _type_ = "i"
186 _check_size(c_int)
188 class c_uint(_SimpleCData):
189 _type_ = "I"
190 _check_size(c_uint)
192class c_float(_SimpleCData):
193 _type_ = "f"
194_check_size(c_float)
196class c_double(_SimpleCData):
197 _type_ = "d"
198_check_size(c_double)
200class c_longdouble(_SimpleCData):
201 _type_ = "g"
202if sizeof(c_longdouble) == sizeof(c_double):
203 c_longdouble = c_double
205if _calcsize("l") == _calcsize("q"):
206 # if long and long long have the same size, make c_longlong an alias for c_long
207 c_longlong = c_long
208 c_ulonglong = c_ulong
209else:
210 class c_longlong(_SimpleCData):
211 _type_ = "q"
212 _check_size(c_longlong)
214 class c_ulonglong(_SimpleCData):
215 _type_ = "Q"
216 ## def from_param(cls, val):
217 ## return ('d', float(val), val)
218 ## from_param = classmethod(from_param)
219 _check_size(c_ulonglong)
221class c_ubyte(_SimpleCData):
222 _type_ = "B"
223c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte
224# backward compatibility:
225##c_uchar = c_ubyte
226_check_size(c_ubyte)
228class c_byte(_SimpleCData):
229 _type_ = "b"
230c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte
231_check_size(c_byte)
233class c_char(_SimpleCData):
234 _type_ = "c"
235c_char.__ctype_le__ = c_char.__ctype_be__ = c_char
236_check_size(c_char)
238class c_char_p(_SimpleCData):
239 _type_ = "z"
240 def __repr__(self):
241 return "%s(%s)" % (self.__class__.__name__, c_void_p.from_buffer(self).value)
242_check_size(c_char_p, "P")
244class c_void_p(_SimpleCData):
245 _type_ = "P"
246c_voidp = c_void_p # backwards compatibility (to a bug)
247_check_size(c_void_p)
249class c_bool(_SimpleCData):
250 _type_ = "?"
252from _ctypes import POINTER, pointer, _pointer_type_cache
254class c_wchar_p(_SimpleCData):
255 _type_ = "Z"
256 def __repr__(self):
257 return "%s(%s)" % (self.__class__.__name__, c_void_p.from_buffer(self).value)
259class c_wchar(_SimpleCData):
260 _type_ = "u"
262def _reset_cache():
263 _pointer_type_cache.clear()
264 _c_functype_cache.clear()
265 if _os.name == "nt":
266 _win_functype_cache.clear()
267 # _SimpleCData.c_wchar_p_from_param
268 POINTER(c_wchar).from_param = c_wchar_p.from_param
269 # _SimpleCData.c_char_p_from_param
270 POINTER(c_char).from_param = c_char_p.from_param
271 _pointer_type_cache[None] = c_void_p
273def create_unicode_buffer(init, size=None):
274 """create_unicode_buffer(aString) -> character array
275 create_unicode_buffer(anInteger) -> character array
276 create_unicode_buffer(aString, anInteger) -> character array
277 """
278 if isinstance(init, str):
279 if size is None:
280 if sizeof(c_wchar) == 2:
281 # UTF-16 requires a surrogate pair (2 wchar_t) for non-BMP
282 # characters (outside [U+0000; U+FFFF] range). +1 for trailing
283 # NUL character.
284 size = sum(2 if ord(c) > 0xFFFF else 1 for c in init) + 1
285 else:
286 # 32-bit wchar_t (1 wchar_t per Unicode character). +1 for
287 # trailing NUL character.
288 size = len(init) + 1
289 _sys.audit("ctypes.create_unicode_buffer", init, size)
290 buftype = c_wchar * size
291 buf = buftype()
292 buf.value = init
293 return buf
294 elif isinstance(init, int):
295 _sys.audit("ctypes.create_unicode_buffer", None, init)
296 buftype = c_wchar * init
297 buf = buftype()
298 return buf
299 raise TypeError(init)
302# XXX Deprecated
303def SetPointerType(pointer, cls):
304 if _pointer_type_cache.get(cls, None) is not None:
305 raise RuntimeError("This type already exists in the cache")
306 if id(pointer) not in _pointer_type_cache:
307 raise RuntimeError("What's this???")
308 pointer.set_type(cls)
309 _pointer_type_cache[cls] = pointer
310 del _pointer_type_cache[id(pointer)]
312# XXX Deprecated
313def ARRAY(typ, len):
314 return typ * len
316################################################################
319class CDLL(object):
320 """An instance of this class represents a loaded dll/shared
321 library, exporting functions using the standard C calling
322 convention (named 'cdecl' on Windows).
324 The exported functions can be accessed as attributes, or by
325 indexing with the function name. Examples:
327 <obj>.qsort -> callable object
328 <obj>['qsort'] -> callable object
330 Calling the functions releases the Python GIL during the call and
331 reacquires it afterwards.
332 """
333 _func_flags_ = _FUNCFLAG_CDECL
334 _func_restype_ = c_int
335 # default values for repr
336 _name = '<uninitialized>'
337 _handle = 0
338 _FuncPtr = None
340 def __init__(self, name, mode=DEFAULT_MODE, handle=None,
341 use_errno=False,
342 use_last_error=False,
343 winmode=None):
344 self._name = name
345 flags = self._func_flags_
346 if use_errno:
347 flags |= _FUNCFLAG_USE_ERRNO
348 if use_last_error:
349 flags |= _FUNCFLAG_USE_LASTERROR
350 if _sys.platform.startswith("aix"):
351 """When the name contains ".a(" and ends with ")",
352 e.g., "libFOO.a(libFOO.so)" - this is taken to be an
353 archive(member) syntax for dlopen(), and the mode is adjusted.
354 Otherwise, name is presented to dlopen() as a file argument.
355 """
356 if name and name.endswith(")") and ".a(" in name:
357 mode |= ( _os.RTLD_MEMBER | _os.RTLD_NOW )
358 if _os.name == "nt":
359 if winmode is not None:
360 mode = winmode
361 else:
362 import nt
363 mode = nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
364 if '/' in name or '\\' in name:
365 self._name = nt._getfullpathname(self._name)
366 mode |= nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
368 class _FuncPtr(_CFuncPtr):
369 _flags_ = flags
370 _restype_ = self._func_restype_
371 self._FuncPtr = _FuncPtr
373 if handle is None:
374 self._handle = _dlopen(self._name, mode)
375 else:
376 self._handle = handle
378 def __repr__(self):
379 return "<%s '%s', handle %x at %#x>" % \
380 (self.__class__.__name__, self._name,
381 (self._handle & (_sys.maxsize*2 + 1)),
382 id(self) & (_sys.maxsize*2 + 1))
384 def __getattr__(self, name):
385 if name.startswith('__') and name.endswith('__'):
386 raise AttributeError(name)
387 func = self.__getitem__(name)
388 setattr(self, name, func)
389 return func
391 def __getitem__(self, name_or_ordinal):
392 func = self._FuncPtr((name_or_ordinal, self))
393 if not isinstance(name_or_ordinal, int):
394 func.__name__ = name_or_ordinal
395 return func
397class PyDLL(CDLL):
398 """This class represents the Python library itself. It allows
399 accessing Python API functions. The GIL is not released, and
400 Python exceptions are handled correctly.
401 """
402 _func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
404if _os.name == "nt":
406 class WinDLL(CDLL):
407 """This class represents a dll exporting functions using the
408 Windows stdcall calling convention.
409 """
410 _func_flags_ = _FUNCFLAG_STDCALL
412 # XXX Hm, what about HRESULT as normal parameter?
413 # Mustn't it derive from c_long then?
414 from _ctypes import _check_HRESULT, _SimpleCData
415 class HRESULT(_SimpleCData):
416 _type_ = "l"
417 # _check_retval_ is called with the function's result when it
418 # is used as restype. It checks for the FAILED bit, and
419 # raises an OSError if it is set.
420 #
421 # The _check_retval_ method is implemented in C, so that the
422 # method definition itself is not included in the traceback
423 # when it raises an error - that is what we want (and Python
424 # doesn't have a way to raise an exception in the caller's
425 # frame).
426 _check_retval_ = _check_HRESULT
428 class OleDLL(CDLL):
429 """This class represents a dll exporting functions using the
430 Windows stdcall calling convention, and returning HRESULT.
431 HRESULT error values are automatically raised as OSError
432 exceptions.
433 """
434 _func_flags_ = _FUNCFLAG_STDCALL
435 _func_restype_ = HRESULT
437class LibraryLoader(object):
438 def __init__(self, dlltype):
439 self._dlltype = dlltype
441 def __getattr__(self, name):
442 if name[0] == '_':
443 raise AttributeError(name)
444 dll = self._dlltype(name)
445 setattr(self, name, dll)
446 return dll
448 def __getitem__(self, name):
449 return getattr(self, name)
451 def LoadLibrary(self, name):
452 return self._dlltype(name)
454 __class_getitem__ = classmethod(_types.GenericAlias)
456cdll = LibraryLoader(CDLL)
457pydll = LibraryLoader(PyDLL)
459if _os.name == "nt":
460 pythonapi = PyDLL("python dll", None, _sys.dllhandle)
461elif _sys.platform == "cygwin":
462 pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
463else:
464 pythonapi = PyDLL(None)
467if _os.name == "nt":
468 windll = LibraryLoader(WinDLL)
469 oledll = LibraryLoader(OleDLL)
471 GetLastError = windll.kernel32.GetLastError
472 from _ctypes import get_last_error, set_last_error
474 def WinError(code=None, descr=None):
475 if code is None:
476 code = GetLastError()
477 if descr is None:
478 descr = FormatError(code).strip()
479 return OSError(None, descr, None, code)
481if sizeof(c_uint) == sizeof(c_void_p):
482 c_size_t = c_uint
483 c_ssize_t = c_int
484elif sizeof(c_ulong) == sizeof(c_void_p):
485 c_size_t = c_ulong
486 c_ssize_t = c_long
487elif sizeof(c_ulonglong) == sizeof(c_void_p):
488 c_size_t = c_ulonglong
489 c_ssize_t = c_longlong
491# functions
493from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
495## void *memmove(void *, const void *, size_t);
496memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
498## void *memset(void *, int, size_t)
499memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
501def PYFUNCTYPE(restype, *argtypes):
502 class CFunctionType(_CFuncPtr):
503 _argtypes_ = argtypes
504 _restype_ = restype
505 _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
506 return CFunctionType
508_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
509def cast(obj, typ):
510 return _cast(obj, obj, typ)
512_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
513def string_at(ptr, size=-1):
514 """string_at(addr[, size]) -> string
516 Return the string at addr."""
517 return _string_at(ptr, size)
519try:
520 from _ctypes import _wstring_at_addr
521except ImportError:
522 pass
523else:
524 _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
525 def wstring_at(ptr, size=-1):
526 """wstring_at(addr[, size]) -> string
528 Return the string at addr."""
529 return _wstring_at(ptr, size)
532if _os.name == "nt": # COM stuff
533 def DllGetClassObject(rclsid, riid, ppv):
534 try:
535 ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
536 except ImportError:
537 return -2147221231 # CLASS_E_CLASSNOTAVAILABLE
538 else:
539 return ccom.DllGetClassObject(rclsid, riid, ppv)
541 def DllCanUnloadNow():
542 try:
543 ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
544 except ImportError:
545 return 0 # S_OK
546 return ccom.DllCanUnloadNow()
548from ctypes._endian import BigEndianStructure, LittleEndianStructure
550# Fill in specifically-sized types
551c_int8 = c_byte
552c_uint8 = c_ubyte
553for kind in [c_short, c_int, c_long, c_longlong]:
554 if sizeof(kind) == 2: c_int16 = kind
555 elif sizeof(kind) == 4: c_int32 = kind
556 elif sizeof(kind) == 8: c_int64 = kind
557for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]:
558 if sizeof(kind) == 2: c_uint16 = kind
559 elif sizeof(kind) == 4: c_uint32 = kind
560 elif sizeof(kind) == 8: c_uint64 = kind
561del(kind)
563_reset_cache()