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