• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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
385class 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
392if _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
425class 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
442cdll = LibraryLoader(CDLL)
443pydll = LibraryLoader(PyDLL)
444
445if _os.name in ("nt", "ce"):
446    pythonapi = PyDLL("python dll", None, _sys.dllhandle)
447elif _sys.platform == "cygwin":
448    pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
449else:
450    pythonapi = PyDLL(None)
451
452
453if _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
470if sizeof(c_uint) == sizeof(c_void_p):
471    c_size_t = c_uint
472    c_ssize_t = c_int
473elif sizeof(c_ulong) == sizeof(c_void_p):
474    c_size_t = c_ulong
475    c_ssize_t = c_long
476elif sizeof(c_ulonglong) == sizeof(c_void_p):
477    c_size_t = c_ulonglong
478    c_ssize_t = c_longlong
479
480# functions
481
482from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
483
484## void *memmove(void *, const void *, size_t);
485memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
486
487## void *memset(void *, int, size_t)
488memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
489
490def 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)
498def cast(obj, typ):
499    return _cast(obj, obj, typ)
500
501_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
502def 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
508try:
509    from _ctypes import _wstring_at_addr
510except ImportError:
511    pass
512else:
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
521if _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
537from ctypes._endian import BigEndianStructure, LittleEndianStructure
538
539# Fill in specifically-sized types
540c_int8 = c_byte
541c_uint8 = c_ubyte
542for 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
546for 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
550del(kind)
551
552_reset_cache()
553