Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/ctypes/__init__.py: 5%

345 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +0000

1"""create and manipulate C data types in Python""" 

2 

3import os as _os, sys as _sys 

4 

5__version__ = "1.1.0" 

6 

7from _ctypes import Union, Structure, Array 

8from _ctypes import _Pointer 

9from _ctypes import CFuncPtr as _CFuncPtr 

10from _ctypes import __version__ as _ctypes_version 

11from _ctypes import RTLD_LOCAL, RTLD_GLOBAL 

12from _ctypes import ArgumentError 

13 

14from struct import calcsize as _calcsize 

15 

16if __version__ != _ctypes_version: 

17 raise Exception("Version number mismatch", __version__, _ctypes_version) 

18 

19if _os.name == "nt": 

20 from _ctypes import FormatError 

21 

22DEFAULT_MODE = RTLD_LOCAL 

23if _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 

27 # that. 

28 

29 if int(_os.uname().release.split('.')[0]) < 8: 

30 DEFAULT_MODE = RTLD_GLOBAL 

31 

32from _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 

36 

37# WINOLEAPI -> HRESULT 

38# WINOLEAPI_(type) 

39# 

40# STDMETHODCALLTYPE 

41# 

42# STDMETHOD(name) 

43# STDMETHOD_(type, name) 

44# 

45# STDAPICALLTYPE 

46 

47def create_string_buffer(init, size=None): 

48 """create_string_buffer(aBytes) -> character array 

49 create_string_buffer(anInteger) -> character array 

50 create_string_buffer(aBytes, anInteger) -> character array 

51 """ 

52 if isinstance(init, bytes): 

53 if size is None: 

54 size = len(init)+1 

55 _sys.audit("ctypes.create_string_buffer", init, size) 

56 buftype = c_char * size 

57 buf = buftype() 

58 buf.value = init 

59 return buf 

60 elif isinstance(init, int): 

61 _sys.audit("ctypes.create_string_buffer", None, init) 

62 buftype = c_char * init 

63 buf = buftype() 

64 return buf 

65 raise TypeError(init) 

66 

67def c_buffer(init, size=None): 

68## "deprecated, use create_string_buffer instead" 

69## import warnings 

70## warnings.warn("c_buffer is deprecated, use create_string_buffer instead", 

71## DeprecationWarning, stacklevel=2) 

72 return create_string_buffer(init, size) 

73 

74_c_functype_cache = {} 

75def CFUNCTYPE(restype, *argtypes, **kw): 

76 """CFUNCTYPE(restype, *argtypes, 

77 use_errno=False, use_last_error=False) -> function prototype. 

78 

79 restype: the result type 

80 argtypes: a sequence specifying the argument types 

81 

82 The function prototype can be called in different ways to create a 

83 callable object: 

84 

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 

90 """ 

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 

96 if kw: 

97 raise ValueError("unexpected keyword argument(s) %s" % kw.keys()) 

98 try: 

99 return _c_functype_cache[(restype, argtypes, flags)] 

100 except KeyError: 

101 class CFunctionType(_CFuncPtr): 

102 _argtypes_ = argtypes 

103 _restype_ = restype 

104 _flags_ = flags 

105 _c_functype_cache[(restype, argtypes, flags)] = CFunctionType 

106 return CFunctionType 

107 

108if _os.name == "nt": 

109 from _ctypes import LoadLibrary as _dlopen 

110 from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL 

111 

112 _win_functype_cache = {} 

113 def WINFUNCTYPE(restype, *argtypes, **kw): 

114 # docstring set later (very similar to CFUNCTYPE.__doc__) 

115 flags = _FUNCFLAG_STDCALL 

116 if kw.pop("use_errno", False): 

117 flags |= _FUNCFLAG_USE_ERRNO 

118 if kw.pop("use_last_error", False): 

119 flags |= _FUNCFLAG_USE_LASTERROR 

120 if kw: 

121 raise ValueError("unexpected keyword argument(s) %s" % kw.keys()) 

122 try: 

123 return _win_functype_cache[(restype, argtypes, flags)] 

124 except KeyError: 

125 class WinFunctionType(_CFuncPtr): 

126 _argtypes_ = argtypes 

127 _restype_ = restype 

128 _flags_ = flags 

129 _win_functype_cache[(restype, argtypes, flags)] = WinFunctionType 

130 return WinFunctionType 

131 if WINFUNCTYPE.__doc__: 

132 WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE") 

133 

134elif _os.name == "posix": 

135 from _ctypes import dlopen as _dlopen 

136 

137from _ctypes import sizeof, byref, addressof, alignment, resize 

138from _ctypes import get_errno, set_errno 

139from _ctypes import _SimpleCData 

140 

141def _check_size(typ, typecode=None): 

142 # Check if sizeof(ctypes_type) against struct.calcsize. This 

143 # should protect somewhat against a misconfigured libffi. 

144 from struct import calcsize 

145 if typecode is None: 

146 # Most _type_ codes are the same as used in struct 

147 typecode = typ._type_ 

148 actual, required = sizeof(typ), calcsize(typecode) 

149 if actual != required: 

150 raise SystemError("sizeof(%s) wrong: %d instead of %d" % \ 

151 (typ, actual, required)) 

152 

153class py_object(_SimpleCData): 

154 _type_ = "O" 

155 def __repr__(self): 

156 try: 

157 return super().__repr__() 

158 except ValueError: 

159 return "%s(<NULL>)" % type(self).__name__ 

160_check_size(py_object, "P") 

161 

162class c_short(_SimpleCData): 

163 _type_ = "h" 

164_check_size(c_short) 

165 

166class c_ushort(_SimpleCData): 

167 _type_ = "H" 

168_check_size(c_ushort) 

169 

170class c_long(_SimpleCData): 

171 _type_ = "l" 

172_check_size(c_long) 

173 

174class c_ulong(_SimpleCData): 

175 _type_ = "L" 

176_check_size(c_ulong) 

177 

178if _calcsize("i") == _calcsize("l"): 

179 # if int and long have the same size, make c_int an alias for c_long 

180 c_int = c_long 

181 c_uint = c_ulong 

182else: 

183 class c_int(_SimpleCData): 

184 _type_ = "i" 

185 _check_size(c_int) 

186 

187 class c_uint(_SimpleCData): 

188 _type_ = "I" 

189 _check_size(c_uint) 

190 

191class c_float(_SimpleCData): 

192 _type_ = "f" 

193_check_size(c_float) 

194 

195class c_double(_SimpleCData): 

196 _type_ = "d" 

197_check_size(c_double) 

198 

199class c_longdouble(_SimpleCData): 

200 _type_ = "g" 

201if sizeof(c_longdouble) == sizeof(c_double): 

202 c_longdouble = c_double 

203 

204if _calcsize("l") == _calcsize("q"): 

205 # if long and long long have the same size, make c_longlong an alias for c_long 

206 c_longlong = c_long 

207 c_ulonglong = c_ulong 

208else: 

209 class c_longlong(_SimpleCData): 

210 _type_ = "q" 

211 _check_size(c_longlong) 

212 

213 class c_ulonglong(_SimpleCData): 

214 _type_ = "Q" 

215 ## def from_param(cls, val): 

216 ## return ('d', float(val), val) 

217 ## from_param = classmethod(from_param) 

218 _check_size(c_ulonglong) 

219 

220class c_ubyte(_SimpleCData): 

221 _type_ = "B" 

222c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte 

223# backward compatibility: 

224##c_uchar = c_ubyte 

225_check_size(c_ubyte) 

226 

227class c_byte(_SimpleCData): 

228 _type_ = "b" 

229c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte 

230_check_size(c_byte) 

231 

232class c_char(_SimpleCData): 

233 _type_ = "c" 

234c_char.__ctype_le__ = c_char.__ctype_be__ = c_char 

235_check_size(c_char) 

236 

237class c_char_p(_SimpleCData): 

238 _type_ = "z" 

239 def __repr__(self): 

240 return "%s(%s)" % (self.__class__.__name__, c_void_p.from_buffer(self).value) 

241_check_size(c_char_p, "P") 

242 

243class c_void_p(_SimpleCData): 

244 _type_ = "P" 

245c_voidp = c_void_p # backwards compatibility (to a bug) 

246_check_size(c_void_p) 

247 

248class c_bool(_SimpleCData): 

249 _type_ = "?" 

250 

251from _ctypes import POINTER, pointer, _pointer_type_cache 

252 

253class c_wchar_p(_SimpleCData): 

254 _type_ = "Z" 

255 def __repr__(self): 

256 return "%s(%s)" % (self.__class__.__name__, c_void_p.from_buffer(self).value) 

257 

258class c_wchar(_SimpleCData): 

259 _type_ = "u" 

260 

261def _reset_cache(): 

262 _pointer_type_cache.clear() 

263 _c_functype_cache.clear() 

264 if _os.name == "nt": 

265 _win_functype_cache.clear() 

266 # _SimpleCData.c_wchar_p_from_param 

267 POINTER(c_wchar).from_param = c_wchar_p.from_param 

268 # _SimpleCData.c_char_p_from_param 

269 POINTER(c_char).from_param = c_char_p.from_param 

270 _pointer_type_cache[None] = c_void_p 

271 

272def create_unicode_buffer(init, size=None): 

273 """create_unicode_buffer(aString) -> character array 

274 create_unicode_buffer(anInteger) -> character array 

275 create_unicode_buffer(aString, anInteger) -> character array 

276 """ 

277 if isinstance(init, str): 

278 if size is None: 

279 if sizeof(c_wchar) == 2: 

280 # UTF-16 requires a surrogate pair (2 wchar_t) for non-BMP 

281 # characters (outside [U+0000; U+FFFF] range). +1 for trailing 

282 # NUL character. 

283 size = sum(2 if ord(c) > 0xFFFF else 1 for c in init) + 1 

284 else: 

285 # 32-bit wchar_t (1 wchar_t per Unicode character). +1 for 

286 # trailing NUL character. 

287 size = len(init) + 1 

288 _sys.audit("ctypes.create_unicode_buffer", init, size) 

289 buftype = c_wchar * size 

290 buf = buftype() 

291 buf.value = init 

292 return buf 

293 elif isinstance(init, int): 

294 _sys.audit("ctypes.create_unicode_buffer", None, init) 

295 buftype = c_wchar * init 

296 buf = buftype() 

297 return buf 

298 raise TypeError(init) 

299 

300 

301# XXX Deprecated 

302def SetPointerType(pointer, cls): 

303 if _pointer_type_cache.get(cls, None) is not None: 

304 raise RuntimeError("This type already exists in the cache") 

305 if id(pointer) not in _pointer_type_cache: 

306 raise RuntimeError("What's this???") 

307 pointer.set_type(cls) 

308 _pointer_type_cache[cls] = pointer 

309 del _pointer_type_cache[id(pointer)] 

310 

311# XXX Deprecated 

312def ARRAY(typ, len): 

313 return typ * len 

314 

315################################################################ 

316 

317 

318class CDLL(object): 

319 """An instance of this class represents a loaded dll/shared 

320 library, exporting functions using the standard C calling 

321 convention (named 'cdecl' on Windows). 

322 

323 The exported functions can be accessed as attributes, or by 

324 indexing with the function name. Examples: 

325 

326 <obj>.qsort -> callable object 

327 <obj>['qsort'] -> callable object 

328 

329 Calling the functions releases the Python GIL during the call and 

330 reacquires it afterwards. 

331 """ 

332 _func_flags_ = _FUNCFLAG_CDECL 

333 _func_restype_ = c_int 

334 # default values for repr 

335 _name = '<uninitialized>' 

336 _handle = 0 

337 _FuncPtr = None 

338 

339 def __init__(self, name, mode=DEFAULT_MODE, handle=None, 

340 use_errno=False, 

341 use_last_error=False, 

342 winmode=None): 

343 self._name = name 

344 flags = self._func_flags_ 

345 if use_errno: 

346 flags |= _FUNCFLAG_USE_ERRNO 

347 if use_last_error: 

348 flags |= _FUNCFLAG_USE_LASTERROR 

349 if _sys.platform.startswith("aix"): 

350 """When the name contains ".a(" and ends with ")", 

351 e.g., "libFOO.a(libFOO.so)" - this is taken to be an 

352 archive(member) syntax for dlopen(), and the mode is adjusted. 

353 Otherwise, name is presented to dlopen() as a file argument. 

354 """ 

355 if name and name.endswith(")") and ".a(" in name: 

356 mode |= ( _os.RTLD_MEMBER | _os.RTLD_NOW ) 

357 if _os.name == "nt": 

358 if winmode is not None: 

359 mode = winmode 

360 else: 

361 import nt 

362 mode = nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 

363 if '/' in name or '\\' in name: 

364 self._name = nt._getfullpathname(self._name) 

365 mode |= nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 

366 

367 class _FuncPtr(_CFuncPtr): 

368 _flags_ = flags 

369 _restype_ = self._func_restype_ 

370 self._FuncPtr = _FuncPtr 

371 

372 if handle is None: 

373 self._handle = _dlopen(self._name, mode) 

374 else: 

375 self._handle = handle 

376 

377 def __repr__(self): 

378 return "<%s '%s', handle %x at %#x>" % \ 

379 (self.__class__.__name__, self._name, 

380 (self._handle & (_sys.maxsize*2 + 1)), 

381 id(self) & (_sys.maxsize*2 + 1)) 

382 

383 def __getattr__(self, name): 

384 if name.startswith('__') and name.endswith('__'): 

385 raise AttributeError(name) 

386 func = self.__getitem__(name) 

387 setattr(self, name, func) 

388 return func 

389 

390 def __getitem__(self, name_or_ordinal): 

391 func = self._FuncPtr((name_or_ordinal, self)) 

392 if not isinstance(name_or_ordinal, int): 

393 func.__name__ = name_or_ordinal 

394 return func 

395 

396class PyDLL(CDLL): 

397 """This class represents the Python library itself. It allows 

398 accessing Python API functions. The GIL is not released, and 

399 Python exceptions are handled correctly. 

400 """ 

401 _func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI 

402 

403if _os.name == "nt": 

404 

405 class WinDLL(CDLL): 

406 """This class represents a dll exporting functions using the 

407 Windows stdcall calling convention. 

408 """ 

409 _func_flags_ = _FUNCFLAG_STDCALL 

410 

411 # XXX Hm, what about HRESULT as normal parameter? 

412 # Mustn't it derive from c_long then? 

413 from _ctypes import _check_HRESULT, _SimpleCData 

414 class HRESULT(_SimpleCData): 

415 _type_ = "l" 

416 # _check_retval_ is called with the function's result when it 

417 # is used as restype. It checks for the FAILED bit, and 

418 # raises an OSError if it is set. 

419 # 

420 # The _check_retval_ method is implemented in C, so that the 

421 # method definition itself is not included in the traceback 

422 # when it raises an error - that is what we want (and Python 

423 # doesn't have a way to raise an exception in the caller's 

424 # frame). 

425 _check_retval_ = _check_HRESULT 

426 

427 class OleDLL(CDLL): 

428 """This class represents a dll exporting functions using the 

429 Windows stdcall calling convention, and returning HRESULT. 

430 HRESULT error values are automatically raised as OSError 

431 exceptions. 

432 """ 

433 _func_flags_ = _FUNCFLAG_STDCALL 

434 _func_restype_ = HRESULT 

435 

436class LibraryLoader(object): 

437 def __init__(self, dlltype): 

438 self._dlltype = dlltype 

439 

440 def __getattr__(self, name): 

441 if name[0] == '_': 

442 raise AttributeError(name) 

443 dll = self._dlltype(name) 

444 setattr(self, name, dll) 

445 return dll 

446 

447 def __getitem__(self, name): 

448 return getattr(self, name) 

449 

450 def LoadLibrary(self, name): 

451 return self._dlltype(name) 

452 

453cdll = LibraryLoader(CDLL) 

454pydll = LibraryLoader(PyDLL) 

455 

456if _os.name == "nt": 

457 pythonapi = PyDLL("python dll", None, _sys.dllhandle) 

458elif _sys.platform == "cygwin": 

459 pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2]) 

460else: 

461 pythonapi = PyDLL(None) 

462 

463 

464if _os.name == "nt": 

465 windll = LibraryLoader(WinDLL) 

466 oledll = LibraryLoader(OleDLL) 

467 

468 GetLastError = windll.kernel32.GetLastError 

469 from _ctypes import get_last_error, set_last_error 

470 

471 def WinError(code=None, descr=None): 

472 if code is None: 

473 code = GetLastError() 

474 if descr is None: 

475 descr = FormatError(code).strip() 

476 return OSError(None, descr, None, code) 

477 

478if sizeof(c_uint) == sizeof(c_void_p): 

479 c_size_t = c_uint 

480 c_ssize_t = c_int 

481elif sizeof(c_ulong) == sizeof(c_void_p): 

482 c_size_t = c_ulong 

483 c_ssize_t = c_long 

484elif sizeof(c_ulonglong) == sizeof(c_void_p): 

485 c_size_t = c_ulonglong 

486 c_ssize_t = c_longlong 

487 

488# functions 

489 

490from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr 

491 

492## void *memmove(void *, const void *, size_t); 

493memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr) 

494 

495## void *memset(void *, int, size_t) 

496memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr) 

497 

498def PYFUNCTYPE(restype, *argtypes): 

499 class CFunctionType(_CFuncPtr): 

500 _argtypes_ = argtypes 

501 _restype_ = restype 

502 _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI 

503 return CFunctionType 

504 

505_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr) 

506def cast(obj, typ): 

507 return _cast(obj, obj, typ) 

508 

509_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) 

510def string_at(ptr, size=-1): 

511 """string_at(addr[, size]) -> string 

512 

513 Return the string at addr.""" 

514 return _string_at(ptr, size) 

515 

516try: 

517 from _ctypes import _wstring_at_addr 

518except ImportError: 

519 pass 

520else: 

521 _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) 

522 def wstring_at(ptr, size=-1): 

523 """wstring_at(addr[, size]) -> string 

524 

525 Return the string at addr.""" 

526 return _wstring_at(ptr, size) 

527 

528 

529if _os.name == "nt": # COM stuff 

530 def DllGetClassObject(rclsid, riid, ppv): 

531 try: 

532 ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*']) 

533 except ImportError: 

534 return -2147221231 # CLASS_E_CLASSNOTAVAILABLE 

535 else: 

536 return ccom.DllGetClassObject(rclsid, riid, ppv) 

537 

538 def DllCanUnloadNow(): 

539 try: 

540 ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*']) 

541 except ImportError: 

542 return 0 # S_OK 

543 return ccom.DllCanUnloadNow() 

544 

545from ctypes._endian import BigEndianStructure, LittleEndianStructure 

546 

547# Fill in specifically-sized types 

548c_int8 = c_byte 

549c_uint8 = c_ubyte 

550for kind in [c_short, c_int, c_long, c_longlong]: 

551 if sizeof(kind) == 2: c_int16 = kind 

552 elif sizeof(kind) == 4: c_int32 = kind 

553 elif sizeof(kind) == 8: c_int64 = kind 

554for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]: 

555 if sizeof(kind) == 2: c_uint16 = kind 

556 elif sizeof(kind) == 4: c_uint32 = kind 

557 elif sizeof(kind) == 8: c_uint64 = kind 

558del(kind) 

559 

560_reset_cache()