PageRenderTime 88ms CodeModel.GetById 37ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 1ms

/Lib/ctypes/__init__.py

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