blob: eb5d97e1879610af67355d1305979f4cdbe71363 [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 Wouters00ee7ba2006-08-21 19:07:27 +00008__version__ = "1.0.1"
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"
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000138 def __repr__(self):
139 try:
140 return super(py_object, self).__repr__()
141 except ValueError:
142 return "%s(<NULL>)" % type(self).__name__
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000143
144class c_short(_SimpleCData):
145 _type_ = "h"
146
147class c_ushort(_SimpleCData):
148 _type_ = "H"
149
150class c_long(_SimpleCData):
151 _type_ = "l"
152
153class c_ulong(_SimpleCData):
154 _type_ = "L"
Tim Peterse8d09e52006-03-09 01:15:05 +0000155
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000156if _calcsize("i") == _calcsize("l"):
157 # if int and long have the same size, make c_int an alias for c_long
158 c_int = c_long
159 c_uint = c_ulong
160else:
161 class c_int(_SimpleCData):
162 _type_ = "i"
163
164 class c_uint(_SimpleCData):
165 _type_ = "I"
166
167class c_float(_SimpleCData):
168 _type_ = "f"
Tim Peterse8d09e52006-03-09 01:15:05 +0000169
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000170class c_double(_SimpleCData):
171 _type_ = "d"
172
173if _calcsize("l") == _calcsize("q"):
174 # if long and long long have the same size, make c_longlong an alias for c_long
175 c_longlong = c_long
176 c_ulonglong = c_ulong
177else:
178 class c_longlong(_SimpleCData):
179 _type_ = "q"
180
181 class c_ulonglong(_SimpleCData):
182 _type_ = "Q"
183 ## def from_param(cls, val):
184 ## return ('d', float(val), val)
185 ## from_param = classmethod(from_param)
186
187class c_ubyte(_SimpleCData):
188 _type_ = "B"
189c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte
190# backward compatibility:
191##c_uchar = c_ubyte
192
193class c_byte(_SimpleCData):
194 _type_ = "b"
195c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte
196
197class c_char(_SimpleCData):
198 _type_ = "c"
199c_char.__ctype_le__ = c_char.__ctype_be__ = c_char
200
201class c_char_p(_SimpleCData):
202 _type_ = "z"
203
204class c_void_p(_SimpleCData):
205 _type_ = "P"
206c_voidp = c_void_p # backwards compatibility (to a bug)
207
208# This cache maps types to pointers to them.
209_pointer_type_cache = {}
210
211def POINTER(cls):
212 try:
213 return _pointer_type_cache[cls]
214 except KeyError:
215 pass
216 if type(cls) is str:
217 klass = type(_Pointer)("LP_%s" % cls,
218 (_Pointer,),
219 {})
220 _pointer_type_cache[id(klass)] = klass
221 return klass
222 else:
223 name = "LP_%s" % cls.__name__
224 klass = type(_Pointer)(name,
225 (_Pointer,),
226 {'_type_': cls})
227 _pointer_type_cache[cls] = klass
228 return klass
229
230try:
231 from _ctypes import set_conversion_mode
232except ImportError:
233 pass
234else:
235 if _os.name in ("nt", "ce"):
236 set_conversion_mode("mbcs", "ignore")
237 else:
238 set_conversion_mode("ascii", "strict")
239
240 class c_wchar_p(_SimpleCData):
241 _type_ = "Z"
242
243 class c_wchar(_SimpleCData):
244 _type_ = "u"
245
246 POINTER(c_wchar).from_param = c_wchar_p.from_param #_SimpleCData.c_wchar_p_from_param
247
248 def create_unicode_buffer(init, size=None):
249 """create_unicode_buffer(aString) -> character array
250 create_unicode_buffer(anInteger) -> character array
251 create_unicode_buffer(aString, anInteger) -> character array
252 """
253 if isinstance(init, (str, unicode)):
254 if size is None:
255 size = len(init)+1
256 buftype = c_wchar * size
257 buf = buftype()
258 buf.value = init
259 return buf
260 elif isinstance(init, (int, long)):
261 buftype = c_wchar * init
262 buf = buftype()
263 return buf
264 raise TypeError, init
265
266POINTER(c_char).from_param = c_char_p.from_param #_SimpleCData.c_char_p_from_param
267
268# XXX Deprecated
269def SetPointerType(pointer, cls):
270 if _pointer_type_cache.get(cls, None) is not None:
271 raise RuntimeError, \
272 "This type already exists in the cache"
Guido van Rossum1b01e5c2006-08-19 02:45:06 +0000273 if id(pointer) not in _pointer_type_cache:
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000274 raise RuntimeError, \
275 "What's this???"
276 pointer.set_type(cls)
277 _pointer_type_cache[cls] = pointer
278 del _pointer_type_cache[id(pointer)]
279
280
281def pointer(inst):
282 return POINTER(type(inst))(inst)
283
284# XXX Deprecated
285def ARRAY(typ, len):
286 return typ * len
287
288################################################################
289
290
291class CDLL(object):
292 """An instance of this class represents a loaded dll/shared
293 library, exporting functions using the standard C calling
294 convention (named 'cdecl' on Windows).
295
296 The exported functions can be accessed as attributes, or by
297 indexing with the function name. Examples:
298
299 <obj>.qsort -> callable object
300 <obj>['qsort'] -> callable object
301
302 Calling the functions releases the Python GIL during the call and
303 reaquires it afterwards.
304 """
305 class _FuncPtr(_CFuncPtr):
306 _flags_ = _FUNCFLAG_CDECL
307 _restype_ = c_int # default, can be overridden in instances
308
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000309 def __init__(self, name, mode=DEFAULT_MODE, handle=None):
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000310 self._name = name
311 if handle is None:
312 self._handle = _dlopen(self._name, mode)
313 else:
314 self._handle = handle
315
316 def __repr__(self):
317 return "<%s '%s', handle %x at %x>" % \
318 (self.__class__.__name__, self._name,
319 (self._handle & (_sys.maxint*2 + 1)),
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000320 id(self) & (_sys.maxint*2 + 1))
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000321
322 def __getattr__(self, name):
323 if name.startswith('__') and name.endswith('__'):
324 raise AttributeError, name
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000325 func = self.__getitem__(name)
326 setattr(self, name, func)
327 return func
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000328
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000329 def __getitem__(self, name_or_ordinal):
330 func = self._FuncPtr((name_or_ordinal, self))
331 if not isinstance(name_or_ordinal, (int, long)):
332 func.__name__ = name_or_ordinal
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000333 return func
334
335class PyDLL(CDLL):
336 """This class represents the Python library itself. It allows to
337 access Python API functions. The GIL is not released, and
338 Python exceptions are handled correctly.
339 """
340 class _FuncPtr(_CFuncPtr):
341 _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
342 _restype_ = c_int # default, can be overridden in instances
343
344if _os.name in ("nt", "ce"):
Tim Peterse8d09e52006-03-09 01:15:05 +0000345
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000346 class WinDLL(CDLL):
347 """This class represents a dll exporting functions using the
348 Windows stdcall calling convention.
349 """
350 class _FuncPtr(_CFuncPtr):
351 _flags_ = _FUNCFLAG_STDCALL
352 _restype_ = c_int # default, can be overridden in instances
353
354 # XXX Hm, what about HRESULT as normal parameter?
355 # Mustn't it derive from c_long then?
356 from _ctypes import _check_HRESULT, _SimpleCData
357 class HRESULT(_SimpleCData):
358 _type_ = "l"
359 # _check_retval_ is called with the function's result when it
360 # is used as restype. It checks for the FAILED bit, and
361 # raises a WindowsError if it is set.
362 #
363 # The _check_retval_ method is implemented in C, so that the
364 # method definition itself is not included in the traceback
365 # when it raises an error - that is what we want (and Python
366 # doesn't have a way to raise an exception in the caller's
367 # frame).
368 _check_retval_ = _check_HRESULT
Tim Peterse8d09e52006-03-09 01:15:05 +0000369
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000370 class OleDLL(CDLL):
371 """This class represents a dll exporting functions using the
372 Windows stdcall calling convention, and returning HRESULT.
373 HRESULT error values are automatically raised as WindowsError
374 exceptions.
375 """
376 class _FuncPtr(_CFuncPtr):
377 _flags_ = _FUNCFLAG_STDCALL
378 _restype_ = HRESULT
379
Thomas Wouters477c8d52006-05-27 19:21:47 +0000380class LibraryLoader(object):
381 def __init__(self, dlltype):
382 self._dlltype = dlltype
383
384 def __getattr__(self, name):
385 if name[0] == '_':
386 raise AttributeError(name)
387 dll = self._dlltype(name)
388 setattr(self, name, dll)
389 return dll
390
391 def __getitem__(self, name):
392 return getattr(self, name)
393
394 def LoadLibrary(self, name):
395 return self._dlltype(name)
396
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000397cdll = LibraryLoader(CDLL)
398pydll = LibraryLoader(PyDLL)
399
400if _os.name in ("nt", "ce"):
401 pythonapi = PyDLL("python dll", None, _sys.dllhandle)
402elif _sys.platform == "cygwin":
403 pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
404else:
405 pythonapi = PyDLL(None)
406
407
408if _os.name in ("nt", "ce"):
409 windll = LibraryLoader(WinDLL)
410 oledll = LibraryLoader(OleDLL)
411
412 if _os.name == "nt":
413 GetLastError = windll.kernel32.GetLastError
414 else:
415 GetLastError = windll.coredll.GetLastError
416
417 def WinError(code=None, descr=None):
418 if code is None:
419 code = GetLastError()
420 if descr is None:
421 descr = FormatError(code).strip()
422 return WindowsError(code, descr)
423
424_pointer_type_cache[None] = c_void_p
425
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000426if sizeof(c_uint) == sizeof(c_void_p):
427 c_size_t = c_uint
428elif sizeof(c_ulong) == sizeof(c_void_p):
429 c_size_t = c_ulong
Thomas Wouters89f507f2006-12-13 04:49:30 +0000430elif sizeof(c_ulonglong) == sizeof(c_void_p):
431 c_size_t = c_ulonglong
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000432
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000433# functions
434
435from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
436
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000437## void *memmove(void *, const void *, size_t);
438memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
439
440## void *memset(void *, int, size_t)
441memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
442
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000443def PYFUNCTYPE(restype, *argtypes):
444 class CFunctionType(_CFuncPtr):
445 _argtypes_ = argtypes
446 _restype_ = restype
447 _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
448 return CFunctionType
Thomas Wouters477c8d52006-05-27 19:21:47 +0000449
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000450_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000451def cast(obj, typ):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000452 return _cast(obj, obj, typ)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000453
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000454_string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
455def string_at(ptr, size=0):
456 """string_at(addr[, size]) -> string
457
458 Return the string at addr."""
459 return _string_at(ptr, size)
460
461try:
462 from _ctypes import _wstring_at_addr
463except ImportError:
464 pass
465else:
466 _wstring_at = CFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
467 def wstring_at(ptr, size=0):
468 """wstring_at(addr[, size]) -> string
469
470 Return the string at addr."""
471 return _wstring_at(ptr, size)
Tim Peterse8d09e52006-03-09 01:15:05 +0000472
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000473
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000474if _os.name in ("nt", "ce"): # COM stuff
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000475 def DllGetClassObject(rclsid, riid, ppv):
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000476 try:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000477 ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000478 except ImportError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000479 return -2147221231 # CLASS_E_CLASSNOTAVAILABLE
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000480 else:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000481 return ccom.DllGetClassObject(rclsid, riid, ppv)
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000482
483 def DllCanUnloadNow():
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000484 try:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000485 ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000486 except ImportError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000487 return 0 # S_OK
488 return ccom.DllCanUnloadNow()
Thomas Hellerbabddfc2006-03-08 19:56:54 +0000489
490from ctypes._endian import BigEndianStructure, LittleEndianStructure
491
492# Fill in specifically-sized types
493c_int8 = c_byte
494c_uint8 = c_ubyte
495for kind in [c_short, c_int, c_long, c_longlong]:
496 if sizeof(kind) == 2: c_int16 = kind
497 elif sizeof(kind) == 4: c_int32 = kind
498 elif sizeof(kind) == 8: c_int64 = kind
499for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]:
500 if sizeof(kind) == 2: c_uint16 = kind
501 elif sizeof(kind) == 4: c_uint32 = kind
502 elif sizeof(kind) == 8: c_uint64 = kind
503del(kind)