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 in ("nt", "ce"):
     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()[2].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 """
     38 WINOLEAPI -> HRESULT
     39 WINOLEAPI_(type)
     40 
     41 STDMETHODCALLTYPE
     42 
     43 STDMETHOD(name)
     44 STDMETHOD_(type, name)
     45 
     46 STDAPICALLTYPE
     47 """
     48 
     49 def 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 
     67 def 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 = {}
     75 def 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 
    108 if _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 
    137 elif _os.name == "posix":
    138     from _ctypes import dlopen as _dlopen
    139 
    140 from _ctypes import sizeof, byref, addressof, alignment, resize
    141 from _ctypes import get_errno, set_errno
    142 from _ctypes import _SimpleCData
    143 
    144 def _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 
    156 class 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 
    165 class c_short(_SimpleCData):
    166     _type_ = "h"
    167 _check_size(c_short)
    168 
    169 class c_ushort(_SimpleCData):
    170     _type_ = "H"
    171 _check_size(c_ushort)
    172 
    173 class c_long(_SimpleCData):
    174     _type_ = "l"
    175 _check_size(c_long)
    176 
    177 class c_ulong(_SimpleCData):
    178     _type_ = "L"
    179 _check_size(c_ulong)
    180 
    181 if _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
    185 else:
    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 
    194 class c_float(_SimpleCData):
    195     _type_ = "f"
    196 _check_size(c_float)
    197 
    198 class c_double(_SimpleCData):
    199     _type_ = "d"
    200 _check_size(c_double)
    201 
    202 class c_longdouble(_SimpleCData):
    203     _type_ = "g"
    204 if sizeof(c_longdouble) == sizeof(c_double):
    205     c_longdouble = c_double
    206 
    207 if _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
    211 else:
    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 
    223 class c_ubyte(_SimpleCData):
    224     _type_ = "B"
    225 c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte
    226 # backward compatibility:
    227 ##c_uchar = c_ubyte
    228 _check_size(c_ubyte)
    229 
    230 class c_byte(_SimpleCData):
    231     _type_ = "b"
    232 c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte
    233 _check_size(c_byte)
    234 
    235 class c_char(_SimpleCData):
    236     _type_ = "c"
    237 c_char.__ctype_le__ = c_char.__ctype_be__ = c_char
    238 _check_size(c_char)
    239 
    240 class 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 
    252 class c_void_p(_SimpleCData):
    253     _type_ = "P"
    254 c_voidp = c_void_p # backwards compatibility (to a bug)
    255 _check_size(c_void_p)
    256 
    257 class c_bool(_SimpleCData):
    258     _type_ = "?"
    259 
    260 from _ctypes import POINTER, pointer, _pointer_type_cache
    261 
    262 def _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 
    278 try:
    279     from _ctypes import set_conversion_mode
    280 except ImportError:
    281     pass
    282 else:
    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
    313 def 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
    323 def ARRAY(typ, len):
    324     return typ * len
    325 
    326 ################################################################
    327 
    328 
    329 class 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 
    346     def __init__(self, name, mode=DEFAULT_MODE, handle=None,
    347                  use_errno=False,
    348                  use_last_error=False):
    349         self._name = name
    350         flags = self._func_flags_
    351         if use_errno:
    352             flags |= _FUNCFLAG_USE_ERRNO
    353         if use_last_error:
    354             flags |= _FUNCFLAG_USE_LASTERROR
    355 
    356         class _FuncPtr(_CFuncPtr):
    357             _flags_ = flags
    358             _restype_ = self._func_restype_
    359         self._FuncPtr = _FuncPtr
    360 
    361         if handle is None:
    362             self._handle = _dlopen(self._name, mode)
    363         else:
    364             self._handle = handle
    365 
    366     def __repr__(self):
    367         return "<%s '%s', handle %x at %x>" % \
    368                (self.__class__.__name__, self._name,
    369                 (self._handle & (_sys.maxint*2 + 1)),
    370                 id(self) & (_sys.maxint*2 + 1))
    371 
    372     def __getattr__(self, name):
    373         if name.startswith('__') and name.endswith('__'):
    374             raise AttributeError(name)
    375         func = self.__getitem__(name)
    376         setattr(self, name, func)
    377         return func
    378 
    379     def __getitem__(self, name_or_ordinal):
    380         func = self._FuncPtr((name_or_ordinal, self))
    381         if not isinstance(name_or_ordinal, (int, long)):
    382             func.__name__ = name_or_ordinal
    383         return func
    384 
    385 class PyDLL(CDLL):
    386     """This class represents the Python library itself.  It allows
    387     accessing Python API functions.  The GIL is not released, and
    388     Python exceptions are handled correctly.
    389     """
    390     _func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
    391 
    392 if _os.name in ("nt", "ce"):
    393 
    394     class WinDLL(CDLL):
    395         """This class represents a dll exporting functions using the
    396         Windows stdcall calling convention.
    397         """
    398         _func_flags_ = _FUNCFLAG_STDCALL
    399 
    400     # XXX Hm, what about HRESULT as normal parameter?
    401     # Mustn't it derive from c_long then?
    402     from _ctypes import _check_HRESULT, _SimpleCData
    403     class HRESULT(_SimpleCData):
    404         _type_ = "l"
    405         # _check_retval_ is called with the function's result when it
    406         # is used as restype.  It checks for the FAILED bit, and
    407         # raises a WindowsError if it is set.
    408         #
    409         # The _check_retval_ method is implemented in C, so that the
    410         # method definition itself is not included in the traceback
    411         # when it raises an error - that is what we want (and Python
    412         # doesn't have a way to raise an exception in the caller's
    413         # frame).
    414         _check_retval_ = _check_HRESULT
    415 
    416     class OleDLL(CDLL):
    417         """This class represents a dll exporting functions using the
    418         Windows stdcall calling convention, and returning HRESULT.
    419         HRESULT error values are automatically raised as WindowsError
    420         exceptions.
    421         """
    422         _func_flags_ = _FUNCFLAG_STDCALL
    423         _func_restype_ = HRESULT
    424 
    425 class LibraryLoader(object):
    426     def __init__(self, dlltype):
    427         self._dlltype = dlltype
    428 
    429     def __getattr__(self, name):
    430         if name[0] == '_':
    431             raise AttributeError(name)
    432         dll = self._dlltype(name)
    433         setattr(self, name, dll)
    434         return dll
    435 
    436     def __getitem__(self, name):
    437         return getattr(self, name)
    438 
    439     def LoadLibrary(self, name):
    440         return self._dlltype(name)
    441 
    442 cdll = LibraryLoader(CDLL)
    443 pydll = LibraryLoader(PyDLL)
    444 
    445 if _os.name in ("nt", "ce"):
    446     pythonapi = PyDLL("python dll", None, _sys.dllhandle)
    447 elif _sys.platform == "cygwin":
    448     pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
    449 else:
    450     pythonapi = PyDLL(None)
    451 
    452 
    453 if _os.name in ("nt", "ce"):
    454     windll = LibraryLoader(WinDLL)
    455     oledll = LibraryLoader(OleDLL)
    456 
    457     if _os.name == "nt":
    458         GetLastError = windll.kernel32.GetLastError
    459     else:
    460         GetLastError = windll.coredll.GetLastError
    461     from _ctypes import get_last_error, set_last_error
    462 
    463     def WinError(code=None, descr=None):
    464         if code is None:
    465             code = GetLastError()
    466         if descr is None:
    467             descr = FormatError(code).strip()
    468         return WindowsError(code, descr)
    469 
    470 if sizeof(c_uint) == sizeof(c_void_p):
    471     c_size_t = c_uint
    472     c_ssize_t = c_int
    473 elif sizeof(c_ulong) == sizeof(c_void_p):
    474     c_size_t = c_ulong
    475     c_ssize_t = c_long
    476 elif sizeof(c_ulonglong) == sizeof(c_void_p):
    477     c_size_t = c_ulonglong
    478     c_ssize_t = c_longlong
    479 
    480 # functions
    481 
    482 from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
    483 
    484 ## void *memmove(void *, const void *, size_t);
    485 memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
    486 
    487 ## void *memset(void *, int, size_t)
    488 memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
    489 
    490 def PYFUNCTYPE(restype, *argtypes):
    491     class CFunctionType(_CFuncPtr):
    492         _argtypes_ = argtypes
    493         _restype_ = restype
    494         _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
    495     return CFunctionType
    496 
    497 _cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
    498 def cast(obj, typ):
    499     return _cast(obj, obj, typ)
    500 
    501 _string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
    502 def string_at(ptr, size=-1):
    503     """string_at(addr[, size]) -> string
    504 
    505     Return the string at addr."""
    506     return _string_at(ptr, size)
    507 
    508 try:
    509     from _ctypes import _wstring_at_addr
    510 except ImportError:
    511     pass
    512 else:
    513     _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
    514     def wstring_at(ptr, size=-1):
    515         """wstring_at(addr[, size]) -> string
    516 
    517         Return the string at addr."""
    518         return _wstring_at(ptr, size)
    519 
    520 
    521 if _os.name in ("nt", "ce"): # COM stuff
    522     def DllGetClassObject(rclsid, riid, ppv):
    523         try:
    524             ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
    525         except ImportError:
    526             return -2147221231 # CLASS_E_CLASSNOTAVAILABLE
    527         else:
    528             return ccom.DllGetClassObject(rclsid, riid, ppv)
    529 
    530     def DllCanUnloadNow():
    531         try:
    532             ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
    533         except ImportError:
    534             return 0 # S_OK
    535         return ccom.DllCanUnloadNow()
    536 
    537 from ctypes._endian import BigEndianStructure, LittleEndianStructure
    538 
    539 # Fill in specifically-sized types
    540 c_int8 = c_byte
    541 c_uint8 = c_ubyte
    542 for kind in [c_short, c_int, c_long, c_longlong]:
    543     if sizeof(kind) == 2: c_int16 = kind
    544     elif sizeof(kind) == 4: c_int32 = kind
    545     elif sizeof(kind) == 8: c_int64 = kind
    546 for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]:
    547     if sizeof(kind) == 2: c_uint16 = kind
    548     elif sizeof(kind) == 4: c_uint32 = kind
    549     elif sizeof(kind) == 8: c_uint64 = kind
    550 del(kind)
    551 
    552 _reset_cache()
    553