blob: a4e3c36e74fba16f232a447c67f3feb55d46182b [file] [log] [blame]
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001######################################################################
2# This file should be kept compatible with Python 2.3, see PEP 291. #
3######################################################################
Thomas Hellerbabddfc2006-03-08 19:56:54 +00004"""create and manipulate C data types in Python"""
5
Thomas Hellerbabddfc2006-03-08 19:56:54 +00006import os as _os, sys as _sys
Thomas Hellerbabddfc2006-03-08 19:56:54 +00007
Thomas Wouters0e3f5912006-08-11 14:57:12 +00008__version__ = "1.0.0"
Thomas Hellerbabddfc2006-03-08 19:56:54 +00009
10from _ctypes import Union, Structure, Array
11from _ctypes import _Pointer
12from _ctypes import CFuncPtr as _CFuncPtr
13from _ctypes import __version__ as _ctypes_version
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000014from _ctypes import RTLD_LOCAL, RTLD_GLOBAL
Thomas Hellerbabddfc2006-03-08 19:56:54 +000015from _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
Thomas Wouters0e3f5912006-08-11 14:57:12 +000025DEFAULT_MODE = RTLD_LOCAL
26if _os.name == "posix" and _sys.platform == "darwin":
27 import gestalt
28
29 # gestalt.gestalt("sysv") returns the version number of the
30 # currently active system file as BCD.
31 # On OS X 10.4.6 -> 0x1046
32 # On OS X 10.2.8 -> 0x1028
33 # See also http://www.rgaros.nl/gestalt/
34 #
35 # On OS X 10.3, we use RTLD_GLOBAL as default mode
36 # because RTLD_LOCAL does not work at least on some
37 # libraries.
38
39 if gestalt.gestalt("sysv") < 0x1040:
40 DEFAULT_MODE = RTLD_GLOBAL
41
Thomas Hellerbabddfc2006-03-08 19:56:54 +000042from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \
43 FUNCFLAG_PYTHONAPI as _FUNCFLAG_PYTHONAPI
44
Thomas Hellerbabddfc2006-03-08 19:56:54 +000045"""
46WINOLEAPI -> HRESULT
47WINOLEAPI_(type)
48
49STDMETHODCALLTYPE
50
51STDMETHOD(name)
52STDMETHOD_(type, name)
53
54STDAPICALLTYPE
55"""
56
57def create_string_buffer(init, size=None):
58 """create_string_buffer(aString) -> character array
59 create_string_buffer(anInteger) -> character array
60 create_string_buffer(aString, anInteger) -> character array
61 """
62 if isinstance(init, (str, unicode)):
63 if size is None:
64 size = len(init)+1
65 buftype = c_char * size
66 buf = buftype()
67 buf.value = init
68 return buf
69 elif isinstance(init, (int, long)):
70 buftype = c_char * init
71 buf = buftype()
72 return buf
73 raise TypeError, init
74
75def c_buffer(init, size=None):
76## "deprecated, use create_string_buffer instead"
77## import warnings
78## warnings.warn("c_buffer is deprecated, use create_string_buffer instead",
79## DeprecationWarning, stacklevel=2)
80 return create_string_buffer(init, size)
81
82_c_functype_cache = {}
83def CFUNCTYPE(restype, *argtypes):
84 """CFUNCTYPE(restype, *argtypes) -> function prototype.
Tim Peterse8d09e52006-03-09 01:15:05 +000085
Thomas Hellerbabddfc2006-03-08 19:56:54 +000086 restype: the result type
87 argtypes: a sequence specifying the argument types
Tim Peterse8d09e52006-03-09 01:15:05 +000088
Thomas Wouters0e3f5912006-08-11 14:57:12 +000089 The function prototype can be called in different ways to create a
Thomas Hellerbabddfc2006-03-08 19:56:54 +000090 callable object:
Tim Peterse8d09e52006-03-09 01:15:05 +000091
Thomas Wouters477c8d52006-05-27 19:21:47 +000092 prototype(integer address) -> foreign function
93 prototype(callable) -> create and return a C callable function from callable
94 prototype(integer index, method name[, paramflags]) -> foreign function calling a COM method
95 prototype((ordinal number, dll object)[, paramflags]) -> foreign function exported by ordinal
96 prototype((function name, dll object)[, paramflags]) -> foreign function exported by name
Thomas Hellerbabddfc2006-03-08 19:56:54 +000097 """
98 try:
99 return _c_functype_cache[(restype, argtypes)]
100 except KeyError:
101 class CFunctionType(_CFuncPtr):
102 _argtypes_ = argtypes
103 _restype_ = restype
104 _flags_ = _FUNCFLAG_CDECL
105 _c_functype_cache[(restype, argtypes)] = 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):
117 # docstring set later (very similar to CFUNCTYPE.__doc__)
118 try:
119 return _win_functype_cache[(restype, argtypes)]
120 except KeyError:
121 class WinFunctionType(_CFuncPtr):
122 _argtypes_ = argtypes
123 _restype_ = restype
124 _flags_ = _FUNCFLAG_STDCALL
125 _win_functype_cache[(restype, argtypes)] = WinFunctionType
126 return WinFunctionType
127 if WINFUNCTYPE.__doc__:
128 WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE")
129
130elif _os.name == "posix":
131 from _ctypes import dlopen as _dlopen
132
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000133from _ctypes import sizeof, byref, addressof, alignment, resize
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000134from _ctypes import _SimpleCData
135
136class py_object(_SimpleCData):
137 _type_ = "O"
138
139class c_short(_SimpleCData):
140 _type_ = "h"
141
142class c_ushort(_SimpleCData):
143 _type_ = "H"
144
145class c_long(_SimpleCData):
146 _type_ = "l"
147
148class c_ulong(_SimpleCData):
149 _type_ = "L"
Tim Peterse8d09e52006-03-09 01:15:05 +0000150
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000151if _calcsize("i") == _calcsize("l"):
152 # if int and long have the same size, make c_int an alias for c_long
153 c_int = c_long
154 c_uint = c_ulong
155else:
156 class c_int(_SimpleCData):
157 _type_ = "i"
158
159 class c_uint(_SimpleCData):
160 _type_ = "I"
161
162class c_float(_SimpleCData):
163 _type_ = "f"
Tim Peterse8d09e52006-03-09 01:15:05 +0000164
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000165class c_double(_SimpleCData):
166 _type_ = "d"
167
168if _calcsize("l") == _calcsize("q"):
169 # if long and long long have the same size, make c_longlong an alias for c_long
170 c_longlong = c_long
171 c_ulonglong = c_ulong
172else:
173 class c_longlong(_SimpleCData):
174 _type_ = "q"
175
176 class c_ulonglong(_SimpleCData):
177 _type_ = "Q"
178 ## def from_param(cls, val):
179 ## return ('d', float(val), val)
180 ## from_param = classmethod(from_param)
181
182class c_ubyte(_SimpleCData):
183 _type_ = "B"
184c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte
185# backward compatibility:
186##c_uchar = c_ubyte
187
188class c_byte(_SimpleCData):
189 _type_ = "b"
190c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte
191
192class c_char(_SimpleCData):
193 _type_ = "c"
194c_char.__ctype_le__ = c_char.__ctype_be__ = c_char
195
196class c_char_p(_SimpleCData):
197 _type_ = "z"
198
199class c_void_p(_SimpleCData):
200 _type_ = "P"
201c_voidp = c_void_p # backwards compatibility (to a bug)
202
203# This cache maps types to pointers to them.
204_pointer_type_cache = {}
205
206def POINTER(cls):
207 try:
208 return _pointer_type_cache[cls]
209 except KeyError:
210 pass
211 if type(cls) is str:
212 klass = type(_Pointer)("LP_%s" % cls,
213 (_Pointer,),
214 {})
215 _pointer_type_cache[id(klass)] = klass
216 return klass
217 else:
218 name = "LP_%s" % cls.__name__
219 klass = type(_Pointer)(name,
220 (_Pointer,),
221 {'_type_': cls})
222 _pointer_type_cache[cls] = klass
223 return klass
224
225try:
226 from _ctypes import set_conversion_mode
227except ImportError:
228 pass
229else:
230 if _os.name in ("nt", "ce"):
231 set_conversion_mode("mbcs", "ignore")
232 else:
233 set_conversion_mode("ascii", "strict")
234
235 class c_wchar_p(_SimpleCData):
236 _type_ = "Z"
237
238 class c_wchar(_SimpleCData):
239 _type_ = "u"
240
241 POINTER(c_wchar).from_param = c_wchar_p.from_param #_SimpleCData.c_wchar_p_from_param
242
243 def create_unicode_buffer(init, size=None):
244 """create_unicode_buffer(aString) -> character array
245 create_unicode_buffer(anInteger) -> character array
246 create_unicode_buffer(aString, anInteger) -> character array
247 """
248 if isinstance(init, (str, unicode)):
249 if size is None:
250 size = len(init)+1
251 buftype = c_wchar * size
252 buf = buftype()
253 buf.value = init
254 return buf
255 elif isinstance(init, (int, long)):
256 buftype = c_wchar * init
257 buf = buftype()
258 return buf
259 raise TypeError, init
260
261POINTER(c_char).from_param = c_char_p.from_param #_SimpleCData.c_char_p_from_param
262
263# XXX Deprecated
264def SetPointerType(pointer, cls):
265 if _pointer_type_cache.get(cls, None) is not None:
266 raise RuntimeError, \
267 "This type already exists in the cache"
268 if not _pointer_type_cache.has_key(id(pointer)):
269 raise RuntimeError, \
270 "What's this???"
271 pointer.set_type(cls)
272 _pointer_type_cache[cls] = pointer
273 del _pointer_type_cache[id(pointer)]
274
275
276def pointer(inst):
277 return POINTER(type(inst))(inst)
278
279# XXX Deprecated
280def ARRAY(typ, len):
281 return typ * len
282
283################################################################
284
285
286class CDLL(object):
287 """An instance of this class represents a loaded dll/shared
288 library, exporting functions using the standard C calling
289 convention (named 'cdecl' on Windows).
290
291 The exported functions can be accessed as attributes, or by
292 indexing with the function name. Examples:
293
294 <obj>.qsort -> callable object
295 <obj>['qsort'] -> callable object
296
297 Calling the functions releases the Python GIL during the call and
298 reaquires it afterwards.
299 """
300 class _FuncPtr(_CFuncPtr):
301 _flags_ = _FUNCFLAG_CDECL
302 _restype_ = c_int # default, can be overridden in instances
303
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000304 def __init__(self, name, mode=DEFAULT_MODE, handle=None):
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000305 self._name = name
306 if handle is None:
307 self._handle = _dlopen(self._name, mode)
308 else:
309 self._handle = handle
310
311 def __repr__(self):
312 return "<%s '%s', handle %x at %x>" % \
313 (self.__class__.__name__, self._name,
314 (self._handle & (_sys.maxint*2 + 1)),
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000315 id(self) & (_sys.maxint*2 + 1))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000316
317 def __getattr__(self, name):
318 if name.startswith('__') and name.endswith('__'):
319 raise AttributeError, name
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000320 func = self.__getitem__(name)
321 setattr(self, name, func)
322 return func
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000323
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000324 def __getitem__(self, name_or_ordinal):
325 func = self._FuncPtr((name_or_ordinal, self))
326 if not isinstance(name_or_ordinal, (int, long)):
327 func.__name__ = name_or_ordinal
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000328 return func
329
330class PyDLL(CDLL):
331 """This class represents the Python library itself. It allows to
332 access Python API functions. The GIL is not released, and
333 Python exceptions are handled correctly.
334 """
335 class _FuncPtr(_CFuncPtr):
336 _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
337 _restype_ = c_int # default, can be overridden in instances
338
339if _os.name in ("nt", "ce"):
Tim Peterse8d09e52006-03-09 01:15:05 +0000340
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000341 class WinDLL(CDLL):
342 """This class represents a dll exporting functions using the
343 Windows stdcall calling convention.
344 """
345 class _FuncPtr(_CFuncPtr):
346 _flags_ = _FUNCFLAG_STDCALL
347 _restype_ = c_int # default, can be overridden in instances
348
349 # XXX Hm, what about HRESULT as normal parameter?
350 # Mustn't it derive from c_long then?
351 from _ctypes import _check_HRESULT, _SimpleCData
352 class HRESULT(_SimpleCData):
353 _type_ = "l"
354 # _check_retval_ is called with the function's result when it
355 # is used as restype. It checks for the FAILED bit, and
356 # raises a WindowsError if it is set.
357 #
358 # The _check_retval_ method is implemented in C, so that the
359 # method definition itself is not included in the traceback
360 # when it raises an error - that is what we want (and Python
361 # doesn't have a way to raise an exception in the caller's
362 # frame).
363 _check_retval_ = _check_HRESULT
Tim Peterse8d09e52006-03-09 01:15:05 +0000364
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000365 class OleDLL(CDLL):
366 """This class represents a dll exporting functions using the
367 Windows stdcall calling convention, and returning HRESULT.
368 HRESULT error values are automatically raised as WindowsError
369 exceptions.
370 """
371 class _FuncPtr(_CFuncPtr):
372 _flags_ = _FUNCFLAG_STDCALL
373 _restype_ = HRESULT
374
Thomas Wouters477c8d52006-05-27 19:21:47 +0000375class LibraryLoader(object):
376 def __init__(self, dlltype):
377 self._dlltype = dlltype
378
379 def __getattr__(self, name):
380 if name[0] == '_':
381 raise AttributeError(name)
382 dll = self._dlltype(name)
383 setattr(self, name, dll)
384 return dll
385
386 def __getitem__(self, name):
387 return getattr(self, name)
388
389 def LoadLibrary(self, name):
390 return self._dlltype(name)
391
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000392cdll = LibraryLoader(CDLL)
393pydll = LibraryLoader(PyDLL)
394
395if _os.name in ("nt", "ce"):
396 pythonapi = PyDLL("python dll", None, _sys.dllhandle)
397elif _sys.platform == "cygwin":
398 pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
399else:
400 pythonapi = PyDLL(None)
401
402
403if _os.name in ("nt", "ce"):
404 windll = LibraryLoader(WinDLL)
405 oledll = LibraryLoader(OleDLL)
406
407 if _os.name == "nt":
408 GetLastError = windll.kernel32.GetLastError
409 else:
410 GetLastError = windll.coredll.GetLastError
411
412 def WinError(code=None, descr=None):
413 if code is None:
414 code = GetLastError()
415 if descr is None:
416 descr = FormatError(code).strip()
417 return WindowsError(code, descr)
418
419_pointer_type_cache[None] = c_void_p
420
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000421if sizeof(c_uint) == sizeof(c_void_p):
422 c_size_t = c_uint
423elif sizeof(c_ulong) == sizeof(c_void_p):
424 c_size_t = c_ulong
425
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000426# functions
427
428from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
429
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000430## void *memmove(void *, const void *, size_t);
431memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
432
433## void *memset(void *, int, size_t)
434memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
435
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000436def PYFUNCTYPE(restype, *argtypes):
437 class CFunctionType(_CFuncPtr):
438 _argtypes_ = argtypes
439 _restype_ = restype
440 _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
441 return CFunctionType
Thomas Wouters477c8d52006-05-27 19:21:47 +0000442
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000443_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000444def cast(obj, typ):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000445 return _cast(obj, obj, typ)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000446
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000447_string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
448def string_at(ptr, size=0):
449 """string_at(addr[, size]) -> string
450
451 Return the string at addr."""
452 return _string_at(ptr, size)
453
454try:
455 from _ctypes import _wstring_at_addr
456except ImportError:
457 pass
458else:
459 _wstring_at = CFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
460 def wstring_at(ptr, size=0):
461 """wstring_at(addr[, size]) -> string
462
463 Return the string at addr."""
464 return _wstring_at(ptr, size)
Tim Peterse8d09e52006-03-09 01:15:05 +0000465
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000466
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000467if _os.name in ("nt", "ce"): # COM stuff
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000468 def DllGetClassObject(rclsid, riid, ppv):
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000469 try:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000470 ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000471 except ImportError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000472 return -2147221231 # CLASS_E_CLASSNOTAVAILABLE
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000473 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000474 return ccom.DllGetClassObject(rclsid, riid, ppv)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000475
476 def DllCanUnloadNow():
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000477 try:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000478 ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000479 except ImportError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000480 return 0 # S_OK
481 return ccom.DllCanUnloadNow()
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000482
483from ctypes._endian import BigEndianStructure, LittleEndianStructure
484
485# Fill in specifically-sized types
486c_int8 = c_byte
487c_uint8 = c_ubyte
488for kind in [c_short, c_int, c_long, c_longlong]:
489 if sizeof(kind) == 2: c_int16 = kind
490 elif sizeof(kind) == 4: c_int32 = kind
491 elif sizeof(kind) == 8: c_int64 = kind
492for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]:
493 if sizeof(kind) == 2: c_uint16 = kind
494 elif sizeof(kind) == 4: c_uint32 = kind
495 elif sizeof(kind) == 8: c_uint64 = kind
496del(kind)