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