1
"""create and manipulate C data types in Python"""
3
import os as _os, sys as _sys
7
from _ctypes import Union, Structure, Array
8
from _ctypes import _Pointer
9
from _ctypes import CFuncPtr as _CFuncPtr
10
from _ctypes import __version__ as _ctypes_version
11
from _ctypes import RTLD_LOCAL, RTLD_GLOBAL
12
from _ctypes import ArgumentError
14
from struct import calcsize as _calcsize
16
if __version__ != _ctypes_version:
17
raise Exception("Version number mismatch", __version__, _ctypes_version)
19
if _os.name in ("nt", "ce"):
20
from _ctypes import FormatError
22
DEFAULT_MODE = RTLD_LOCAL
23
if _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
29
if int(_os.uname()[2].split('.')[0]) < 8:
30
DEFAULT_MODE = RTLD_GLOBAL
32
from _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
44
STDMETHOD_(type, name)
49
def create_string_buffer(init, size=None):
50
"""create_string_buffer(aBytes) -> character array
51
create_string_buffer(anInteger) -> character array
52
create_string_buffer(aString, anInteger) -> character array
54
if isinstance(init, (str, bytes)):
57
buftype = c_char * size
61
elif isinstance(init, int):
62
buftype = c_char * init
67
def c_buffer(init, size=None):
68
## "deprecated, use create_string_buffer instead"
70
## warnings.warn("c_buffer is deprecated, use create_string_buffer instead",
71
## DeprecationWarning, stacklevel=2)
72
return create_string_buffer(init, size)
74
_c_functype_cache = {}
75
def CFUNCTYPE(restype, *argtypes, **kw):
76
"""CFUNCTYPE(restype, *argtypes,
77
use_errno=False, use_last_error=False) -> function prototype.
79
restype: the result type
80
argtypes: a sequence specifying the argument types
82
The function prototype can be called in different ways to create a
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
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
97
raise ValueError("unexpected keyword argument(s) %s" % kw.keys())
99
return _c_functype_cache[(restype, argtypes, flags)]
101
class CFunctionType(_CFuncPtr):
102
_argtypes_ = argtypes
105
_c_functype_cache[(restype, argtypes, flags)] = CFunctionType
108
if _os.name in ("nt", "ce"):
109
from _ctypes import LoadLibrary as _dlopen
110
from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL
112
# 'ce' doesn't have the stdcall calling convention
113
_FUNCFLAG_STDCALL = _FUNCFLAG_CDECL
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
124
raise ValueError("unexpected keyword argument(s) %s" % kw.keys())
126
return _win_functype_cache[(restype, argtypes, flags)]
128
class WinFunctionType(_CFuncPtr):
129
_argtypes_ = argtypes
132
_win_functype_cache[(restype, argtypes, flags)] = WinFunctionType
133
return WinFunctionType
134
if WINFUNCTYPE.__doc__:
135
WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE")
137
elif _os.name == "posix":
138
from _ctypes import dlopen as _dlopen
140
from _ctypes import sizeof, byref, addressof, alignment, resize
141
from _ctypes import get_errno, set_errno
142
from _ctypes import _SimpleCData
144
def _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
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))
156
class py_object(_SimpleCData):
160
return super().__repr__()
162
return "%s(<NULL>)" % type(self).__name__
163
_check_size(py_object, "P")
165
class c_short(_SimpleCData):
169
class c_ushort(_SimpleCData):
171
_check_size(c_ushort)
173
class c_long(_SimpleCData):
177
class c_ulong(_SimpleCData):
181
if _calcsize("i") == _calcsize("l"):
182
# if int and long have the same size, make c_int an alias for c_long
186
class c_int(_SimpleCData):
190
class c_uint(_SimpleCData):
194
class c_float(_SimpleCData):
198
class c_double(_SimpleCData):
200
_check_size(c_double)
202
class c_longdouble(_SimpleCData):
204
if sizeof(c_longdouble) == sizeof(c_double):
205
c_longdouble = c_double
207
if _calcsize("l") == _calcsize("q"):
208
# if long and long long have the same size, make c_longlong an alias for c_long
210
c_ulonglong = c_ulong
212
class c_longlong(_SimpleCData):
214
_check_size(c_longlong)
216
class c_ulonglong(_SimpleCData):
218
## def from_param(cls, val):
219
## return ('d', float(val), val)
220
## from_param = classmethod(from_param)
221
_check_size(c_ulonglong)
223
class c_ubyte(_SimpleCData):
225
c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte
226
# backward compatibility:
230
class c_byte(_SimpleCData):
232
c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte
235
class c_char(_SimpleCData):
237
c_char.__ctype_le__ = c_char.__ctype_be__ = c_char
240
class c_char_p(_SimpleCData):
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)
249
return "%s(%s)" % (self.__class__.__name__, cast(self, c_void_p).value)
250
_check_size(c_char_p, "P")
252
class c_void_p(_SimpleCData):
254
c_voidp = c_void_p # backwards compatibility (to a bug)
255
_check_size(c_void_p)
257
class c_bool(_SimpleCData):
260
from _ctypes import POINTER, pointer, _pointer_type_cache
263
from _ctypes import set_conversion_mode
267
if _os.name in ("nt", "ce"):
268
set_conversion_mode("mbcs", "ignore")
270
set_conversion_mode("ascii", "strict")
272
class c_wchar_p(_SimpleCData):
275
class c_wchar(_SimpleCData):
278
POINTER(c_wchar).from_param = c_wchar_p.from_param #_SimpleCData.c_wchar_p_from_param
280
def create_unicode_buffer(init, size=None):
281
"""create_unicode_buffer(aString) -> character array
282
create_unicode_buffer(anInteger) -> character array
283
create_unicode_buffer(aString, anInteger) -> character array
285
if isinstance(init, (str, bytes)):
288
buftype = c_wchar * size
292
elif isinstance(init, int):
293
buftype = c_wchar * init
296
raise TypeError(init)
298
POINTER(c_char).from_param = c_char_p.from_param #_SimpleCData.c_char_p_from_param
301
def SetPointerType(pointer, cls):
302
if _pointer_type_cache.get(cls, None) is not None:
303
raise RuntimeError("This type already exists in the cache")
304
if id(pointer) not in _pointer_type_cache:
305
raise RuntimeError("What's this???")
306
pointer.set_type(cls)
307
_pointer_type_cache[cls] = pointer
308
del _pointer_type_cache[id(pointer)]
314
################################################################
318
"""An instance of this class represents a loaded dll/shared
319
library, exporting functions using the standard C calling
320
convention (named 'cdecl' on Windows).
322
The exported functions can be accessed as attributes, or by
323
indexing with the function name. Examples:
325
<obj>.qsort -> callable object
326
<obj>['qsort'] -> callable object
328
Calling the functions releases the Python GIL during the call and
329
reacquires it afterwards.
331
_func_flags_ = _FUNCFLAG_CDECL
332
_func_restype_ = c_int
334
def __init__(self, name, mode=DEFAULT_MODE, handle=None,
336
use_last_error=False):
338
flags = self._func_flags_
340
flags |= _FUNCFLAG_USE_ERRNO
342
flags |= _FUNCFLAG_USE_LASTERROR
344
class _FuncPtr(_CFuncPtr):
346
_restype_ = self._func_restype_
347
self._FuncPtr = _FuncPtr
350
self._handle = _dlopen(self._name, mode)
352
self._handle = handle
355
return "<%s '%s', handle %x at %x>" % \
356
(self.__class__.__name__, self._name,
357
(self._handle & (_sys.maxsize*2 + 1)),
358
id(self) & (_sys.maxsize*2 + 1))
360
def __getattr__(self, name):
361
if name.startswith('__') and name.endswith('__'):
362
raise AttributeError(name)
363
func = self.__getitem__(name)
364
setattr(self, name, func)
367
def __getitem__(self, name_or_ordinal):
368
func = self._FuncPtr((name_or_ordinal, self))
369
if not isinstance(name_or_ordinal, int):
370
func.__name__ = name_or_ordinal
374
"""This class represents the Python library itself. It allows to
375
access Python API functions. The GIL is not released, and
376
Python exceptions are handled correctly.
378
_func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
380
if _os.name in ("nt", "ce"):
383
"""This class represents a dll exporting functions using the
384
Windows stdcall calling convention.
386
_func_flags_ = _FUNCFLAG_STDCALL
388
# XXX Hm, what about HRESULT as normal parameter?
389
# Mustn't it derive from c_long then?
390
from _ctypes import _check_HRESULT, _SimpleCData
391
class HRESULT(_SimpleCData):
393
# _check_retval_ is called with the function's result when it
394
# is used as restype. It checks for the FAILED bit, and
395
# raises a WindowsError if it is set.
397
# The _check_retval_ method is implemented in C, so that the
398
# method definition itself is not included in the traceback
399
# when it raises an error - that is what we want (and Python
400
# doesn't have a way to raise an exception in the caller's
402
_check_retval_ = _check_HRESULT
405
"""This class represents a dll exporting functions using the
406
Windows stdcall calling convention, and returning HRESULT.
407
HRESULT error values are automatically raised as WindowsError
410
_func_flags_ = _FUNCFLAG_STDCALL
411
_func_restype_ = HRESULT
413
class LibraryLoader(object):
414
def __init__(self, dlltype):
415
self._dlltype = dlltype
417
def __getattr__(self, name):
419
raise AttributeError(name)
420
dll = self._dlltype(name)
421
setattr(self, name, dll)
424
def __getitem__(self, name):
425
return getattr(self, name)
427
def LoadLibrary(self, name):
428
return self._dlltype(name)
430
cdll = LibraryLoader(CDLL)
431
pydll = LibraryLoader(PyDLL)
433
if _os.name in ("nt", "ce"):
434
pythonapi = PyDLL("python dll", None, _sys.dllhandle)
435
elif _sys.platform == "cygwin":
436
pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
438
pythonapi = PyDLL(None)
441
if _os.name in ("nt", "ce"):
442
windll = LibraryLoader(WinDLL)
443
oledll = LibraryLoader(OleDLL)
446
GetLastError = windll.kernel32.GetLastError
448
GetLastError = windll.coredll.GetLastError
449
from _ctypes import get_last_error, set_last_error
451
def WinError(code=None, descr=None):
453
code = GetLastError()
455
descr = FormatError(code).strip()
456
return WindowsError(code, descr)
458
_pointer_type_cache[None] = c_void_p
460
if sizeof(c_uint) == sizeof(c_void_p):
462
elif sizeof(c_ulong) == sizeof(c_void_p):
464
elif sizeof(c_ulonglong) == sizeof(c_void_p):
465
c_size_t = c_ulonglong
469
from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
471
## void *memmove(void *, const void *, size_t);
472
memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
474
## void *memset(void *, int, size_t)
475
memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
477
def PYFUNCTYPE(restype, *argtypes):
478
class CFunctionType(_CFuncPtr):
479
_argtypes_ = argtypes
481
_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
484
_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
486
return _cast(obj, obj, typ)
488
_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
489
def string_at(ptr, size=-1):
490
"""string_at(addr[, size]) -> string
492
Return the string at addr."""
493
return _string_at(ptr, size)
496
from _ctypes import _wstring_at_addr
500
_wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
501
def wstring_at(ptr, size=-1):
502
"""wstring_at(addr[, size]) -> string
504
Return the string at addr."""
505
return _wstring_at(ptr, size)
508
if _os.name in ("nt", "ce"): # COM stuff
509
def DllGetClassObject(rclsid, riid, ppv):
511
ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
513
return -2147221231 # CLASS_E_CLASSNOTAVAILABLE
515
return ccom.DllGetClassObject(rclsid, riid, ppv)
517
def DllCanUnloadNow():
519
ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
522
return ccom.DllCanUnloadNow()
524
from ctypes._endian import BigEndianStructure, LittleEndianStructure
526
# Fill in specifically-sized types
529
for kind in [c_short, c_int, c_long, c_longlong]:
530
if sizeof(kind) == 2: c_int16 = kind
531
elif sizeof(kind) == 4: c_int32 = kind
532
elif sizeof(kind) == 8: c_int64 = kind
533
for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]:
534
if sizeof(kind) == 2: c_uint16 = kind
535
elif sizeof(kind) == 4: c_uint32 = kind
536
elif sizeof(kind) == 8: c_uint64 = kind
539
# XXX for whatever reasons, creating the first instance of a callback
540
# function is needed for the unittests on Win64 to succeed. This MAY
541
# be a compiler bug, since the problem occurs only when _ctypes is
542
# compiled with the MS SDK compiler. Or an uninitialized variable?
543
CFUNCTYPE(c_int)(lambda: None)