1 """create and manipulate C data types in Python"""
3 import os
as _os
, sys
as _sys
4 from itertools
import chain
as _chain
6 __version__
= "0.9.9.4"
8 from _ctypes
import Union
, Structure
, Array
9 from _ctypes
import _Pointer
10 from _ctypes
import CFuncPtr
as _CFuncPtr
11 from _ctypes
import __version__
as _ctypes_version
13 from _ctypes
import RTLD_LOCAL
, RTLD_GLOBAL
14 except (ImportError, AttributeError):
15 RTLD_GLOBAL
= RTLD_LOCAL
= None
17 from _ctypes
import ArgumentError
19 from struct
import calcsize
as _calcsize
21 if __version__
!= _ctypes_version
:
22 raise Exception, ("Version number mismatch", __version__
, _ctypes_version
)
24 if _os
.name
in ("nt", "ce"):
25 from _ctypes
import FormatError
27 from _ctypes
import FUNCFLAG_CDECL
as _FUNCFLAG_CDECL
, \
28 FUNCFLAG_PYTHONAPI
as _FUNCFLAG_PYTHONAPI
30 from ctypes
._loader
import LibraryLoader
39 STDMETHOD_(type, name)
44 def create_string_buffer(init
, size
=None):
45 """create_string_buffer(aString) -> character array
46 create_string_buffer(anInteger) -> character array
47 create_string_buffer(aString, anInteger) -> character array
49 if isinstance(init
, (str, unicode)):
52 buftype
= c_char
* size
56 elif isinstance(init
, (int, long)):
57 buftype
= c_char
* init
62 def c_buffer(init
, size
=None):
63 ## "deprecated, use create_string_buffer instead"
65 ## warnings.warn("c_buffer is deprecated, use create_string_buffer instead",
66 ## DeprecationWarning, stacklevel=2)
67 return create_string_buffer(init
, size
)
69 _c_functype_cache
= {}
70 def CFUNCTYPE(restype
, *argtypes
):
71 """CFUNCTYPE(restype, *argtypes) -> function prototype.
73 restype: the result type
74 argtypes: a sequence specifying the argument types
76 The function prototype can be called in three ways to create a
79 prototype(funct) - returns a C callable function calling funct
80 prototype(vtbl_index, method_name[, paramflags]) - a Python callable that calls a COM method
81 prototype(funct_name, dll[, paramflags]) - a Python callable that calls an exported function in a dll
84 return _c_functype_cache
[(restype
, argtypes
)]
86 class CFunctionType(_CFuncPtr
):
89 _flags_
= _FUNCFLAG_CDECL
90 _c_functype_cache
[(restype
, argtypes
)] = CFunctionType
93 if _os
.name
in ("nt", "ce"):
94 from _ctypes
import LoadLibrary
as _dlopen
95 from _ctypes
import FUNCFLAG_STDCALL
as _FUNCFLAG_STDCALL
97 # 'ce' doesn't have the stdcall calling convention
98 _FUNCFLAG_STDCALL
= _FUNCFLAG_CDECL
100 _win_functype_cache
= {}
101 def WINFUNCTYPE(restype
, *argtypes
):
102 # docstring set later (very similar to CFUNCTYPE.__doc__)
104 return _win_functype_cache
[(restype
, argtypes
)]
106 class WinFunctionType(_CFuncPtr
):
107 _argtypes_
= argtypes
109 _flags_
= _FUNCFLAG_STDCALL
110 _win_functype_cache
[(restype
, argtypes
)] = WinFunctionType
111 return WinFunctionType
112 if WINFUNCTYPE
.__doc
__:
113 WINFUNCTYPE
.__doc
__ = CFUNCTYPE
.__doc
__.replace("CFUNCTYPE", "WINFUNCTYPE")
115 elif _os
.name
== "posix":
116 from _ctypes
import dlopen
as _dlopen
118 from _ctypes
import sizeof
, byref
, addressof
, alignment
119 from _ctypes
import _SimpleCData
121 class py_object(_SimpleCData
):
124 class c_short(_SimpleCData
):
127 class c_ushort(_SimpleCData
):
130 class c_long(_SimpleCData
):
133 class c_ulong(_SimpleCData
):
136 if _calcsize("i") == _calcsize("l"):
137 # if int and long have the same size, make c_int an alias for c_long
141 class c_int(_SimpleCData
):
144 class c_uint(_SimpleCData
):
147 class c_float(_SimpleCData
):
150 class c_double(_SimpleCData
):
153 if _calcsize("l") == _calcsize("q"):
154 # if long and long long have the same size, make c_longlong an alias for c_long
156 c_ulonglong
= c_ulong
158 class c_longlong(_SimpleCData
):
161 class c_ulonglong(_SimpleCData
):
163 ## def from_param(cls, val):
164 ## return ('d', float(val), val)
165 ## from_param = classmethod(from_param)
167 class c_ubyte(_SimpleCData
):
169 c_ubyte
.__ctype
_le
__ = c_ubyte
.__ctype
_be
__ = c_ubyte
170 # backward compatibility:
173 class c_byte(_SimpleCData
):
175 c_byte
.__ctype
_le
__ = c_byte
.__ctype
_be
__ = c_byte
177 class c_char(_SimpleCData
):
179 c_char
.__ctype
_le
__ = c_char
.__ctype
_be
__ = c_char
181 class c_char_p(_SimpleCData
):
184 class c_void_p(_SimpleCData
):
186 c_voidp
= c_void_p
# backwards compatibility (to a bug)
188 # This cache maps types to pointers to them.
189 _pointer_type_cache
= {}
193 return _pointer_type_cache
[cls
]
197 klass
= type(_Pointer
)("LP_%s" % cls
,
200 _pointer_type_cache
[id(klass
)] = klass
203 name
= "LP_%s" % cls
.__name
__
204 klass
= type(_Pointer
)(name
,
207 _pointer_type_cache
[cls
] = klass
211 from _ctypes
import set_conversion_mode
215 if _os
.name
in ("nt", "ce"):
216 set_conversion_mode("mbcs", "ignore")
218 set_conversion_mode("ascii", "strict")
220 class c_wchar_p(_SimpleCData
):
223 class c_wchar(_SimpleCData
):
226 POINTER(c_wchar
).from_param
= c_wchar_p
.from_param
#_SimpleCData.c_wchar_p_from_param
228 def create_unicode_buffer(init
, size
=None):
229 """create_unicode_buffer(aString) -> character array
230 create_unicode_buffer(anInteger) -> character array
231 create_unicode_buffer(aString, anInteger) -> character array
233 if isinstance(init
, (str, unicode)):
236 buftype
= c_wchar
* size
240 elif isinstance(init
, (int, long)):
241 buftype
= c_wchar
* init
244 raise TypeError, init
246 POINTER(c_char
).from_param
= c_char_p
.from_param
#_SimpleCData.c_char_p_from_param
249 def SetPointerType(pointer
, cls
):
250 if _pointer_type_cache
.get(cls
, None) is not None:
251 raise RuntimeError, \
252 "This type already exists in the cache"
253 if not _pointer_type_cache
.has_key(id(pointer
)):
254 raise RuntimeError, \
256 pointer
.set_type(cls
)
257 _pointer_type_cache
[cls
] = pointer
258 del _pointer_type_cache
[id(pointer
)]
262 return POINTER(type(inst
))(inst
)
268 ################################################################
272 """An instance of this class represents a loaded dll/shared
273 library, exporting functions using the standard C calling
274 convention (named 'cdecl' on Windows).
276 The exported functions can be accessed as attributes, or by
277 indexing with the function name. Examples:
279 <obj>.qsort -> callable object
280 <obj>['qsort'] -> callable object
282 Calling the functions releases the Python GIL during the call and
283 reaquires it afterwards.
285 class _FuncPtr(_CFuncPtr
):
286 _flags_
= _FUNCFLAG_CDECL
287 _restype_
= c_int
# default, can be overridden in instances
289 def __init__(self
, name
, mode
=RTLD_LOCAL
, handle
=None):
292 self
._handle
= _dlopen(self
._name
, mode
)
294 self
._handle
= handle
297 return "<%s '%s', handle %x at %x>" % \
298 (self
.__class
__.__name
__, self
._name
,
299 (self
._handle
& (_sys
.maxint
*2 + 1)),
302 def __getattr__(self
, name
):
303 if name
.startswith('__') and name
.endswith('__'):
304 raise AttributeError, name
305 return self
.__getitem
__(name
)
307 def __getitem__(self
, name
):
308 func
= self
._FuncPtr
(name
, self
)
310 setattr(self
, name
, func
)
314 """This class represents the Python library itself. It allows to
315 access Python API functions. The GIL is not released, and
316 Python exceptions are handled correctly.
318 class _FuncPtr(_CFuncPtr
):
319 _flags_
= _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
320 _restype_
= c_int
# default, can be overridden in instances
322 if _os
.name
in ("nt", "ce"):
325 """This class represents a dll exporting functions using the
326 Windows stdcall calling convention.
328 class _FuncPtr(_CFuncPtr
):
329 _flags_
= _FUNCFLAG_STDCALL
330 _restype_
= c_int
# default, can be overridden in instances
332 # XXX Hm, what about HRESULT as normal parameter?
333 # Mustn't it derive from c_long then?
334 from _ctypes
import _check_HRESULT
, _SimpleCData
335 class HRESULT(_SimpleCData
):
337 # _check_retval_ is called with the function's result when it
338 # is used as restype. It checks for the FAILED bit, and
339 # raises a WindowsError if it is set.
341 # The _check_retval_ method is implemented in C, so that the
342 # method definition itself is not included in the traceback
343 # when it raises an error - that is what we want (and Python
344 # doesn't have a way to raise an exception in the caller's
346 _check_retval_
= _check_HRESULT
349 """This class represents a dll exporting functions using the
350 Windows stdcall calling convention, and returning HRESULT.
351 HRESULT error values are automatically raised as WindowsError
354 class _FuncPtr(_CFuncPtr
):
355 _flags_
= _FUNCFLAG_STDCALL
358 cdll
= LibraryLoader(CDLL
)
359 pydll
= LibraryLoader(PyDLL
)
361 if _os
.name
in ("nt", "ce"):
362 pythonapi
= PyDLL("python dll", None, _sys
.dllhandle
)
363 elif _sys
.platform
== "cygwin":
364 pythonapi
= PyDLL("libpython%d.%d.dll" % _sys
.version_info
[:2])
366 pythonapi
= PyDLL(None)
369 if _os
.name
in ("nt", "ce"):
370 windll
= LibraryLoader(WinDLL
)
371 oledll
= LibraryLoader(OleDLL
)
374 GetLastError
= windll
.kernel32
.GetLastError
376 GetLastError
= windll
.coredll
.GetLastError
378 def WinError(code
=None, descr
=None):
380 code
= GetLastError()
382 descr
= FormatError(code
).strip()
383 return WindowsError(code
, descr
)
385 _pointer_type_cache
[None] = c_void_p
389 from _ctypes
import _memmove_addr
, _memset_addr
, _string_at_addr
, cast
391 if sizeof(c_uint
) == sizeof(c_void_p
):
393 elif sizeof(c_ulong
) == sizeof(c_void_p
):
396 ## void *memmove(void *, const void *, size_t);
397 memmove
= CFUNCTYPE(c_void_p
, c_void_p
, c_void_p
, c_size_t
)(_memmove_addr
)
399 ## void *memset(void *, int, size_t)
400 memset
= CFUNCTYPE(c_void_p
, c_void_p
, c_int
, c_size_t
)(_memset_addr
)
402 _string_at
= CFUNCTYPE(py_object
, c_void_p
, c_int
)(_string_at_addr
)
403 def string_at(ptr
, size
=0):
404 """string_at(addr[, size]) -> string
406 Return the string at addr."""
407 return _string_at(ptr
, size
)
410 from _ctypes
import _wstring_at_addr
414 _wstring_at
= CFUNCTYPE(py_object
, c_void_p
, c_int
)(_wstring_at_addr
)
415 def wstring_at(ptr
, size
=0):
416 """wstring_at(addr[, size]) -> string
418 Return the string at addr."""
419 return _wstring_at(ptr
, size
)
422 if _os
.name
== "nt": # COM stuff
423 def DllGetClassObject(rclsid
, riid
, ppv
):
424 # First ask ctypes.com.server than comtypes.server for the
427 # trick py2exe by doing dynamic imports
428 result
= -2147221231 # CLASS_E_CLASSNOTAVAILABLE
430 ctcom
= __import__("ctypes.com.server", globals(), locals(), ['*'])
434 result
= ctcom
.DllGetClassObject(rclsid
, riid
, ppv
)
436 if result
== -2147221231: # CLASS_E_CLASSNOTAVAILABLE
438 ccom
= __import__("comtypes.server", globals(), locals(), ['*'])
442 result
= ccom
.DllGetClassObject(rclsid
, riid
, ppv
)
446 def DllCanUnloadNow():
447 # First ask ctypes.com.server than comtypes.server if we can unload or not.
448 # trick py2exe by doing dynamic imports
451 ctcom
= __import__("ctypes.com.server", globals(), locals(), ['*'])
455 result
= ctcom
.DllCanUnloadNow()
456 if result
!= 0: # != S_OK
460 ccom
= __import__("comtypes.server", globals(), locals(), ['*'])
464 return ccom
.DllCanUnloadNow()
465 except AttributeError:
469 from ctypes
._endian
import BigEndianStructure
, LittleEndianStructure
471 # Fill in specifically-sized types
474 for kind
in [c_short
, c_int
, c_long
, c_longlong
]:
475 if sizeof(kind
) == 2: c_int16
= kind
476 elif sizeof(kind
) == 4: c_int32
= kind
477 elif sizeof(kind
) == 8: c_int64
= kind
478 for kind
in [c_ushort
, c_uint
, c_ulong
, c_ulonglong
]:
479 if sizeof(kind
) == 2: c_uint16
= kind
480 elif sizeof(kind
) == 4: c_uint32
= kind
481 elif sizeof(kind
) == 8: c_uint64
= kind