Home | History | Annotate | Download | only in ctypes
      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