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