Coverage for /pythoncovmergedfiles/medio/medio/usr/lib/python3.9/ctypes/__init__.py: 1%

347 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-10-20 07:00 +0000

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

2 

3import os as _os, sys as _sys 

4import types as _types 

5 

6__version__ = "1.1.0" 

7 

8from _ctypes import Union, Structure, Array 

9from _ctypes import _Pointer 

10from _ctypes import CFuncPtr as _CFuncPtr 

11from _ctypes import __version__ as _ctypes_version 

12from _ctypes import RTLD_LOCAL, RTLD_GLOBAL 

13from _ctypes import ArgumentError 

14 

15from struct import calcsize as _calcsize 

16 

17if __version__ != _ctypes_version: 

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

19 

20if _os.name == "nt": 

21 from _ctypes import FormatError 

22 

23DEFAULT_MODE = RTLD_LOCAL 

24if _os.name == "posix" and _sys.platform == "darwin": 

25 # On OS X 10.3, we use RTLD_GLOBAL as default mode 

26 # because RTLD_LOCAL does not work at least on some 

27 # libraries. OS X 10.3 is Darwin 7, so we check for 

28 # that. 

29 

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

31 DEFAULT_MODE = RTLD_GLOBAL 

32 

33from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \ 

34 FUNCFLAG_PYTHONAPI as _FUNCFLAG_PYTHONAPI, \ 

35 FUNCFLAG_USE_ERRNO as _FUNCFLAG_USE_ERRNO, \ 

36 FUNCFLAG_USE_LASTERROR as _FUNCFLAG_USE_LASTERROR 

37 

38# WINOLEAPI -> HRESULT 

39# WINOLEAPI_(type) 

40# 

41# STDMETHODCALLTYPE 

42# 

43# STDMETHOD(name) 

44# STDMETHOD_(type, name) 

45# 

46# STDAPICALLTYPE 

47 

48def create_string_buffer(init, size=None): 

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

50 create_string_buffer(anInteger) -> character array 

51 create_string_buffer(aBytes, anInteger) -> character array 

52 """ 

53 if isinstance(init, bytes): 

54 if size is None: 

55 size = len(init)+1 

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

57 buftype = c_char * size 

58 buf = buftype() 

59 buf.value = init 

60 return buf 

61 elif isinstance(init, int): 

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

63 buftype = c_char * init 

64 buf = buftype() 

65 return buf 

66 raise TypeError(init) 

67 

68def c_buffer(init, size=None): 

69## "deprecated, use create_string_buffer instead" 

70## import warnings 

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

72## DeprecationWarning, stacklevel=2) 

73 return create_string_buffer(init, size) 

74 

75_c_functype_cache = {} 

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

77 """CFUNCTYPE(restype, *argtypes, 

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

79 

80 restype: the result type 

81 argtypes: a sequence specifying the argument types 

82 

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

84 callable object: 

85 

86 prototype(integer address) -> foreign function 

87 prototype(callable) -> create and return a C callable function from callable 

88 prototype(integer index, method name[, paramflags]) -> foreign function calling a COM method 

89 prototype((ordinal number, dll object)[, paramflags]) -> foreign function exported by ordinal 

90 prototype((function name, dll object)[, paramflags]) -> foreign function exported by name 

91 """ 

92 flags = _FUNCFLAG_CDECL 

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

94 flags |= _FUNCFLAG_USE_ERRNO 

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

96 flags |= _FUNCFLAG_USE_LASTERROR 

97 if kw: 

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

99 try: 

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

101 except KeyError: 

102 class CFunctionType(_CFuncPtr): 

103 _argtypes_ = argtypes 

104 _restype_ = restype 

105 _flags_ = flags 

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

107 return CFunctionType 

108 

109if _os.name == "nt": 

110 from _ctypes import LoadLibrary as _dlopen 

111 from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL 

112 

113 _win_functype_cache = {} 

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

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

116 flags = _FUNCFLAG_STDCALL 

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

118 flags |= _FUNCFLAG_USE_ERRNO 

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

120 flags |= _FUNCFLAG_USE_LASTERROR 

121 if kw: 

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

123 try: 

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

125 except KeyError: 

126 class WinFunctionType(_CFuncPtr): 

127 _argtypes_ = argtypes 

128 _restype_ = restype 

129 _flags_ = flags 

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

131 return WinFunctionType 

132 if WINFUNCTYPE.__doc__: 

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

134 

135elif _os.name == "posix": 

136 from _ctypes import dlopen as _dlopen 

137 

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

139from _ctypes import get_errno, set_errno 

140from _ctypes import _SimpleCData 

141 

142def _check_size(typ, typecode=None): 

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

144 # should protect somewhat against a misconfigured libffi. 

145 from struct import calcsize 

146 if typecode is None: 

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

148 typecode = typ._type_ 

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

150 if actual != required: 

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

152 (typ, actual, required)) 

153 

154class py_object(_SimpleCData): 

155 _type_ = "O" 

156 def __repr__(self): 

157 try: 

158 return super().__repr__() 

159 except ValueError: 

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

161_check_size(py_object, "P") 

162 

163class c_short(_SimpleCData): 

164 _type_ = "h" 

165_check_size(c_short) 

166 

167class c_ushort(_SimpleCData): 

168 _type_ = "H" 

169_check_size(c_ushort) 

170 

171class c_long(_SimpleCData): 

172 _type_ = "l" 

173_check_size(c_long) 

174 

175class c_ulong(_SimpleCData): 

176 _type_ = "L" 

177_check_size(c_ulong) 

178 

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

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

181 c_int = c_long 

182 c_uint = c_ulong 

183else: 

184 class c_int(_SimpleCData): 

185 _type_ = "i" 

186 _check_size(c_int) 

187 

188 class c_uint(_SimpleCData): 

189 _type_ = "I" 

190 _check_size(c_uint) 

191 

192class c_float(_SimpleCData): 

193 _type_ = "f" 

194_check_size(c_float) 

195 

196class c_double(_SimpleCData): 

197 _type_ = "d" 

198_check_size(c_double) 

199 

200class c_longdouble(_SimpleCData): 

201 _type_ = "g" 

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

203 c_longdouble = c_double 

204 

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

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

207 c_longlong = c_long 

208 c_ulonglong = c_ulong 

209else: 

210 class c_longlong(_SimpleCData): 

211 _type_ = "q" 

212 _check_size(c_longlong) 

213 

214 class c_ulonglong(_SimpleCData): 

215 _type_ = "Q" 

216 ## def from_param(cls, val): 

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

218 ## from_param = classmethod(from_param) 

219 _check_size(c_ulonglong) 

220 

221class c_ubyte(_SimpleCData): 

222 _type_ = "B" 

223c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte 

224# backward compatibility: 

225##c_uchar = c_ubyte 

226_check_size(c_ubyte) 

227 

228class c_byte(_SimpleCData): 

229 _type_ = "b" 

230c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte 

231_check_size(c_byte) 

232 

233class c_char(_SimpleCData): 

234 _type_ = "c" 

235c_char.__ctype_le__ = c_char.__ctype_be__ = c_char 

236_check_size(c_char) 

237 

238class c_char_p(_SimpleCData): 

239 _type_ = "z" 

240 def __repr__(self): 

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

242_check_size(c_char_p, "P") 

243 

244class c_void_p(_SimpleCData): 

245 _type_ = "P" 

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

247_check_size(c_void_p) 

248 

249class c_bool(_SimpleCData): 

250 _type_ = "?" 

251 

252from _ctypes import POINTER, pointer, _pointer_type_cache 

253 

254class c_wchar_p(_SimpleCData): 

255 _type_ = "Z" 

256 def __repr__(self): 

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

258 

259class c_wchar(_SimpleCData): 

260 _type_ = "u" 

261 

262def _reset_cache(): 

263 _pointer_type_cache.clear() 

264 _c_functype_cache.clear() 

265 if _os.name == "nt": 

266 _win_functype_cache.clear() 

267 # _SimpleCData.c_wchar_p_from_param 

268 POINTER(c_wchar).from_param = c_wchar_p.from_param 

269 # _SimpleCData.c_char_p_from_param 

270 POINTER(c_char).from_param = c_char_p.from_param 

271 _pointer_type_cache[None] = c_void_p 

272 

273def create_unicode_buffer(init, size=None): 

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

275 create_unicode_buffer(anInteger) -> character array 

276 create_unicode_buffer(aString, anInteger) -> character array 

277 """ 

278 if isinstance(init, str): 

279 if size is None: 

280 if sizeof(c_wchar) == 2: 

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

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

283 # NUL character. 

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

285 else: 

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

287 # trailing NUL character. 

288 size = len(init) + 1 

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

290 buftype = c_wchar * size 

291 buf = buftype() 

292 buf.value = init 

293 return buf 

294 elif isinstance(init, int): 

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

296 buftype = c_wchar * init 

297 buf = buftype() 

298 return buf 

299 raise TypeError(init) 

300 

301 

302# XXX Deprecated 

303def SetPointerType(pointer, cls): 

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

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

306 if id(pointer) not in _pointer_type_cache: 

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

308 pointer.set_type(cls) 

309 _pointer_type_cache[cls] = pointer 

310 del _pointer_type_cache[id(pointer)] 

311 

312# XXX Deprecated 

313def ARRAY(typ, len): 

314 return typ * len 

315 

316################################################################ 

317 

318 

319class CDLL(object): 

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

321 library, exporting functions using the standard C calling 

322 convention (named 'cdecl' on Windows). 

323 

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

325 indexing with the function name. Examples: 

326 

327 <obj>.qsort -> callable object 

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

329 

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

331 reacquires it afterwards. 

332 """ 

333 _func_flags_ = _FUNCFLAG_CDECL 

334 _func_restype_ = c_int 

335 # default values for repr 

336 _name = '<uninitialized>' 

337 _handle = 0 

338 _FuncPtr = None 

339 

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

341 use_errno=False, 

342 use_last_error=False, 

343 winmode=None): 

344 self._name = name 

345 flags = self._func_flags_ 

346 if use_errno: 

347 flags |= _FUNCFLAG_USE_ERRNO 

348 if use_last_error: 

349 flags |= _FUNCFLAG_USE_LASTERROR 

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

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

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

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

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

355 """ 

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

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

358 if _os.name == "nt": 

359 if winmode is not None: 

360 mode = winmode 

361 else: 

362 import nt 

363 mode = nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 

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

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

366 mode |= nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 

367 

368 class _FuncPtr(_CFuncPtr): 

369 _flags_ = flags 

370 _restype_ = self._func_restype_ 

371 self._FuncPtr = _FuncPtr 

372 

373 if handle is None: 

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

375 else: 

376 self._handle = handle 

377 

378 def __repr__(self): 

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

380 (self.__class__.__name__, self._name, 

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

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

383 

384 def __getattr__(self, name): 

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

386 raise AttributeError(name) 

387 func = self.__getitem__(name) 

388 setattr(self, name, func) 

389 return func 

390 

391 def __getitem__(self, name_or_ordinal): 

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

393 if not isinstance(name_or_ordinal, int): 

394 func.__name__ = name_or_ordinal 

395 return func 

396 

397class PyDLL(CDLL): 

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

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

400 Python exceptions are handled correctly. 

401 """ 

402 _func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI 

403 

404if _os.name == "nt": 

405 

406 class WinDLL(CDLL): 

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

408 Windows stdcall calling convention. 

409 """ 

410 _func_flags_ = _FUNCFLAG_STDCALL 

411 

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

413 # Mustn't it derive from c_long then? 

414 from _ctypes import _check_HRESULT, _SimpleCData 

415 class HRESULT(_SimpleCData): 

416 _type_ = "l" 

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

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

419 # raises an OSError if it is set. 

420 # 

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

422 # method definition itself is not included in the traceback 

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

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

425 # frame). 

426 _check_retval_ = _check_HRESULT 

427 

428 class OleDLL(CDLL): 

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

430 Windows stdcall calling convention, and returning HRESULT. 

431 HRESULT error values are automatically raised as OSError 

432 exceptions. 

433 """ 

434 _func_flags_ = _FUNCFLAG_STDCALL 

435 _func_restype_ = HRESULT 

436 

437class LibraryLoader(object): 

438 def __init__(self, dlltype): 

439 self._dlltype = dlltype 

440 

441 def __getattr__(self, name): 

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

443 raise AttributeError(name) 

444 dll = self._dlltype(name) 

445 setattr(self, name, dll) 

446 return dll 

447 

448 def __getitem__(self, name): 

449 return getattr(self, name) 

450 

451 def LoadLibrary(self, name): 

452 return self._dlltype(name) 

453 

454 __class_getitem__ = classmethod(_types.GenericAlias) 

455 

456cdll = LibraryLoader(CDLL) 

457pydll = LibraryLoader(PyDLL) 

458 

459if _os.name == "nt": 

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

461elif _sys.platform == "cygwin": 

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

463else: 

464 pythonapi = PyDLL(None) 

465 

466 

467if _os.name == "nt": 

468 windll = LibraryLoader(WinDLL) 

469 oledll = LibraryLoader(OleDLL) 

470 

471 GetLastError = windll.kernel32.GetLastError 

472 from _ctypes import get_last_error, set_last_error 

473 

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

475 if code is None: 

476 code = GetLastError() 

477 if descr is None: 

478 descr = FormatError(code).strip() 

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

480 

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

482 c_size_t = c_uint 

483 c_ssize_t = c_int 

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

485 c_size_t = c_ulong 

486 c_ssize_t = c_long 

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

488 c_size_t = c_ulonglong 

489 c_ssize_t = c_longlong 

490 

491# functions 

492 

493from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr 

494 

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

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

497 

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

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

500 

501def PYFUNCTYPE(restype, *argtypes): 

502 class CFunctionType(_CFuncPtr): 

503 _argtypes_ = argtypes 

504 _restype_ = restype 

505 _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI 

506 return CFunctionType 

507 

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

509def cast(obj, typ): 

510 return _cast(obj, obj, typ) 

511 

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

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

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

515 

516 Return the string at addr.""" 

517 return _string_at(ptr, size) 

518 

519try: 

520 from _ctypes import _wstring_at_addr 

521except ImportError: 

522 pass 

523else: 

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

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

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

527 

528 Return the string at addr.""" 

529 return _wstring_at(ptr, size) 

530 

531 

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

533 def DllGetClassObject(rclsid, riid, ppv): 

534 try: 

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

536 except ImportError: 

537 return -2147221231 # CLASS_E_CLASSNOTAVAILABLE 

538 else: 

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

540 

541 def DllCanUnloadNow(): 

542 try: 

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

544 except ImportError: 

545 return 0 # S_OK 

546 return ccom.DllCanUnloadNow() 

547 

548from ctypes._endian import BigEndianStructure, LittleEndianStructure 

549 

550# Fill in specifically-sized types 

551c_int8 = c_byte 

552c_uint8 = c_ubyte 

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

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

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

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

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

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

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

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

561del(kind) 

562 

563_reset_cache()