Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cffi/api.py: 21%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

544 statements  

1import sys, types 

2from .lock import allocate_lock 

3from .error import CDefError 

4from . import model 

5 

6try: 

7 callable 

8except NameError: 

9 # Python 3.1 

10 from collections import Callable 

11 callable = lambda x: isinstance(x, Callable) 

12 

13try: 

14 basestring 

15except NameError: 

16 # Python 3.x 

17 basestring = str 

18 

19_unspecified = object() 

20 

21 

22 

23class FFI(object): 

24 r''' 

25 The main top-level class that you instantiate once, or once per module. 

26 

27 Example usage: 

28 

29 ffi = FFI() 

30 ffi.cdef(""" 

31 int printf(const char *, ...); 

32 """) 

33 

34 C = ffi.dlopen(None) # standard library 

35 -or- 

36 C = ffi.verify() # use a C compiler: verify the decl above is right 

37 

38 C.printf("hello, %s!\n", ffi.new("char[]", "world")) 

39 ''' 

40 

41 def __init__(self, backend=None): 

42 """Create an FFI instance. The 'backend' argument is used to 

43 select a non-default backend, mostly for tests. 

44 """ 

45 if backend is None: 

46 # You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with 

47 # _cffi_backend.so compiled. 

48 import _cffi_backend as backend 

49 from . import __version__ 

50 if backend.__version__ != __version__: 

51 # bad version! Try to be as explicit as possible. 

52 if hasattr(backend, '__file__'): 

53 # CPython 

54 raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r. The two versions should be equal; check your installation." % ( 

55 __version__, __file__, 

56 backend.__version__, backend.__file__)) 

57 else: 

58 # PyPy 

59 raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. This interpreter comes with a built-in '_cffi_backend' module, which is version %s. The two versions should be equal; check your installation." % ( 

60 __version__, __file__, backend.__version__)) 

61 # (If you insist you can also try to pass the option 

62 # 'backend=backend_ctypes.CTypesBackend()', but don't 

63 # rely on it! It's probably not going to work well.) 

64 

65 from . import cparser 

66 self._backend = backend 

67 self._lock = allocate_lock() 

68 self._parser = cparser.Parser() 

69 self._cached_btypes = {} 

70 self._parsed_types = types.ModuleType('parsed_types').__dict__ 

71 self._new_types = types.ModuleType('new_types').__dict__ 

72 self._function_caches = [] 

73 self._libraries = [] 

74 self._cdefsources = [] 

75 self._included_ffis = [] 

76 self._windows_unicode = None 

77 self._init_once_cache = {} 

78 self._cdef_version = None 

79 self._embedding = None 

80 self._typecache = model.get_typecache(backend) 

81 if hasattr(backend, 'set_ffi'): 

82 backend.set_ffi(self) 

83 for name in list(backend.__dict__): 

84 if name.startswith('RTLD_'): 

85 setattr(self, name, getattr(backend, name)) 

86 # 

87 with self._lock: 

88 self.BVoidP = self._get_cached_btype(model.voidp_type) 

89 self.BCharA = self._get_cached_btype(model.char_array_type) 

90 if isinstance(backend, types.ModuleType): 

91 # _cffi_backend: attach these constants to the class 

92 if not hasattr(FFI, 'NULL'): 

93 FFI.NULL = self.cast(self.BVoidP, 0) 

94 FFI.CData, FFI.CType = backend._get_types() 

95 else: 

96 # ctypes backend: attach these constants to the instance 

97 self.NULL = self.cast(self.BVoidP, 0) 

98 self.CData, self.CType = backend._get_types() 

99 self.buffer = backend.buffer 

100 

101 def cdef(self, csource, override=False, packed=False, pack=None): 

102 """Parse the given C source. This registers all declared functions, 

103 types, and global variables. The functions and global variables can 

104 then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'. 

105 The types can be used in 'ffi.new()' and other functions. 

106 If 'packed' is specified as True, all structs declared inside this 

107 cdef are packed, i.e. laid out without any field alignment at all. 

108 Alternatively, 'pack' can be a small integer, and requests for 

109 alignment greater than that are ignored (pack=1 is equivalent to 

110 packed=True). 

111 """ 

112 self._cdef(csource, override=override, packed=packed, pack=pack) 

113 

114 def embedding_api(self, csource, packed=False, pack=None): 

115 self._cdef(csource, packed=packed, pack=pack, dllexport=True) 

116 if self._embedding is None: 

117 self._embedding = '' 

118 

119 def _cdef(self, csource, override=False, **options): 

120 if not isinstance(csource, str): # unicode, on Python 2 

121 if not isinstance(csource, basestring): 

122 raise TypeError("cdef() argument must be a string") 

123 csource = csource.encode('ascii') 

124 with self._lock: 

125 self._cdef_version = object() 

126 self._parser.parse(csource, override=override, **options) 

127 self._cdefsources.append(csource) 

128 if override: 

129 for cache in self._function_caches: 

130 cache.clear() 

131 finishlist = self._parser._recomplete 

132 if finishlist: 

133 self._parser._recomplete = [] 

134 for tp in finishlist: 

135 tp.finish_backend_type(self, finishlist) 

136 

137 def dlopen(self, name, flags=0): 

138 """Load and return a dynamic library identified by 'name'. 

139 The standard C library can be loaded by passing None. 

140 Note that functions and types declared by 'ffi.cdef()' are not 

141 linked to a particular library, just like C headers; in the 

142 library we only look for the actual (untyped) symbols. 

143 """ 

144 if not (isinstance(name, basestring) or 

145 name is None or 

146 isinstance(name, self.CData)): 

147 raise TypeError("dlopen(name): name must be a file name, None, " 

148 "or an already-opened 'void *' handle") 

149 with self._lock: 

150 lib, function_cache = _make_ffi_library(self, name, flags) 

151 self._function_caches.append(function_cache) 

152 self._libraries.append(lib) 

153 return lib 

154 

155 def dlclose(self, lib): 

156 """Close a library obtained with ffi.dlopen(). After this call, 

157 access to functions or variables from the library will fail 

158 (possibly with a segmentation fault). 

159 """ 

160 type(lib).__cffi_close__(lib) 

161 

162 def _typeof_locked(self, cdecl): 

163 # call me with the lock! 

164 key = cdecl 

165 if key in self._parsed_types: 

166 return self._parsed_types[key] 

167 # 

168 if not isinstance(cdecl, str): # unicode, on Python 2 

169 cdecl = cdecl.encode('ascii') 

170 # 

171 type = self._parser.parse_type(cdecl) 

172 really_a_function_type = type.is_raw_function 

173 if really_a_function_type: 

174 type = type.as_function_pointer() 

175 btype = self._get_cached_btype(type) 

176 result = btype, really_a_function_type 

177 self._parsed_types[key] = result 

178 return result 

179 

180 def _typeof(self, cdecl, consider_function_as_funcptr=False): 

181 # string -> ctype object 

182 try: 

183 result = self._parsed_types[cdecl] 

184 except KeyError: 

185 with self._lock: 

186 result = self._typeof_locked(cdecl) 

187 # 

188 btype, really_a_function_type = result 

189 if really_a_function_type and not consider_function_as_funcptr: 

190 raise CDefError("the type %r is a function type, not a " 

191 "pointer-to-function type" % (cdecl,)) 

192 return btype 

193 

194 def typeof(self, cdecl): 

195 """Parse the C type given as a string and return the 

196 corresponding <ctype> object. 

197 It can also be used on 'cdata' instance to get its C type. 

198 """ 

199 if isinstance(cdecl, basestring): 

200 return self._typeof(cdecl) 

201 if isinstance(cdecl, self.CData): 

202 return self._backend.typeof(cdecl) 

203 if isinstance(cdecl, types.BuiltinFunctionType): 

204 res = _builtin_function_type(cdecl) 

205 if res is not None: 

206 return res 

207 if (isinstance(cdecl, types.FunctionType) 

208 and hasattr(cdecl, '_cffi_base_type')): 

209 with self._lock: 

210 return self._get_cached_btype(cdecl._cffi_base_type) 

211 raise TypeError(type(cdecl)) 

212 

213 def sizeof(self, cdecl): 

214 """Return the size in bytes of the argument. It can be a 

215 string naming a C type, or a 'cdata' instance. 

216 """ 

217 if isinstance(cdecl, basestring): 

218 BType = self._typeof(cdecl) 

219 return self._backend.sizeof(BType) 

220 else: 

221 return self._backend.sizeof(cdecl) 

222 

223 def alignof(self, cdecl): 

224 """Return the natural alignment size in bytes of the C type 

225 given as a string. 

226 """ 

227 if isinstance(cdecl, basestring): 

228 cdecl = self._typeof(cdecl) 

229 return self._backend.alignof(cdecl) 

230 

231 def offsetof(self, cdecl, *fields_or_indexes): 

232 """Return the offset of the named field inside the given 

233 structure or array, which must be given as a C type name. 

234 You can give several field names in case of nested structures. 

235 You can also give numeric values which correspond to array 

236 items, in case of an array type. 

237 """ 

238 if isinstance(cdecl, basestring): 

239 cdecl = self._typeof(cdecl) 

240 return self._typeoffsetof(cdecl, *fields_or_indexes)[1] 

241 

242 def new(self, cdecl, init=None): 

243 """Allocate an instance according to the specified C type and 

244 return a pointer to it. The specified C type must be either a 

245 pointer or an array: ``new('X *')`` allocates an X and returns 

246 a pointer to it, whereas ``new('X[n]')`` allocates an array of 

247 n X'es and returns an array referencing it (which works 

248 mostly like a pointer, like in C). You can also use 

249 ``new('X[]', n)`` to allocate an array of a non-constant 

250 length n. 

251 

252 The memory is initialized following the rules of declaring a 

253 global variable in C: by default it is zero-initialized, but 

254 an explicit initializer can be given which can be used to 

255 fill all or part of the memory. 

256 

257 When the returned <cdata> object goes out of scope, the memory 

258 is freed. In other words the returned <cdata> object has 

259 ownership of the value of type 'cdecl' that it points to. This 

260 means that the raw data can be used as long as this object is 

261 kept alive, but must not be used for a longer time. Be careful 

262 about that when copying the pointer to the memory somewhere 

263 else, e.g. into another structure. 

264 """ 

265 if isinstance(cdecl, basestring): 

266 cdecl = self._typeof(cdecl) 

267 return self._backend.newp(cdecl, init) 

268 

269 def new_allocator(self, alloc=None, free=None, 

270 should_clear_after_alloc=True): 

271 """Return a new allocator, i.e. a function that behaves like ffi.new() 

272 but uses the provided low-level 'alloc' and 'free' functions. 

273 

274 'alloc' is called with the size as argument. If it returns NULL, a 

275 MemoryError is raised. 'free' is called with the result of 'alloc' 

276 as argument. Both can be either Python function or directly C 

277 functions. If 'free' is None, then no free function is called. 

278 If both 'alloc' and 'free' are None, the default is used. 

279 

280 If 'should_clear_after_alloc' is set to False, then the memory 

281 returned by 'alloc' is assumed to be already cleared (or you are 

282 fine with garbage); otherwise CFFI will clear it. 

283 """ 

284 compiled_ffi = self._backend.FFI() 

285 allocator = compiled_ffi.new_allocator(alloc, free, 

286 should_clear_after_alloc) 

287 def allocate(cdecl, init=None): 

288 if isinstance(cdecl, basestring): 

289 cdecl = self._typeof(cdecl) 

290 return allocator(cdecl, init) 

291 return allocate 

292 

293 def cast(self, cdecl, source): 

294 """Similar to a C cast: returns an instance of the named C 

295 type initialized with the given 'source'. The source is 

296 casted between integers or pointers of any type. 

297 """ 

298 if isinstance(cdecl, basestring): 

299 cdecl = self._typeof(cdecl) 

300 return self._backend.cast(cdecl, source) 

301 

302 def string(self, cdata, maxlen=-1): 

303 """Return a Python string (or unicode string) from the 'cdata'. 

304 If 'cdata' is a pointer or array of characters or bytes, returns 

305 the null-terminated string. The returned string extends until 

306 the first null character, or at most 'maxlen' characters. If 

307 'cdata' is an array then 'maxlen' defaults to its length. 

308 

309 If 'cdata' is a pointer or array of wchar_t, returns a unicode 

310 string following the same rules. 

311 

312 If 'cdata' is a single character or byte or a wchar_t, returns 

313 it as a string or unicode string. 

314 

315 If 'cdata' is an enum, returns the value of the enumerator as a 

316 string, or 'NUMBER' if the value is out of range. 

317 """ 

318 return self._backend.string(cdata, maxlen) 

319 

320 def unpack(self, cdata, length): 

321 """Unpack an array of C data of the given length, 

322 returning a Python string/unicode/list. 

323 

324 If 'cdata' is a pointer to 'char', returns a byte string. 

325 It does not stop at the first null. This is equivalent to: 

326 ffi.buffer(cdata, length)[:] 

327 

328 If 'cdata' is a pointer to 'wchar_t', returns a unicode string. 

329 'length' is measured in wchar_t's; it is not the size in bytes. 

330 

331 If 'cdata' is a pointer to anything else, returns a list of 

332 'length' items. This is a faster equivalent to: 

333 [cdata[i] for i in range(length)] 

334 """ 

335 return self._backend.unpack(cdata, length) 

336 

337 #def buffer(self, cdata, size=-1): 

338 # """Return a read-write buffer object that references the raw C data 

339 # pointed to by the given 'cdata'. The 'cdata' must be a pointer or 

340 # an array. Can be passed to functions expecting a buffer, or directly 

341 # manipulated with: 

342 # 

343 # buf[:] get a copy of it in a regular string, or 

344 # buf[idx] as a single character 

345 # buf[:] = ... 

346 # buf[idx] = ... change the content 

347 # """ 

348 # note that 'buffer' is a type, set on this instance by __init__ 

349 

350 def from_buffer(self, cdecl, python_buffer=_unspecified, 

351 require_writable=False): 

352 """Return a cdata of the given type pointing to the data of the 

353 given Python object, which must support the buffer interface. 

354 Note that this is not meant to be used on the built-in types 

355 str or unicode (you can build 'char[]' arrays explicitly) 

356 but only on objects containing large quantities of raw data 

357 in some other format, like 'array.array' or numpy arrays. 

358 

359 The first argument is optional and default to 'char[]'. 

360 """ 

361 if python_buffer is _unspecified: 

362 cdecl, python_buffer = self.BCharA, cdecl 

363 elif isinstance(cdecl, basestring): 

364 cdecl = self._typeof(cdecl) 

365 return self._backend.from_buffer(cdecl, python_buffer, 

366 require_writable) 

367 

368 def memmove(self, dest, src, n): 

369 """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest. 

370 

371 Like the C function memmove(), the memory areas may overlap; 

372 apart from that it behaves like the C function memcpy(). 

373 

374 'src' can be any cdata ptr or array, or any Python buffer object. 

375 'dest' can be any cdata ptr or array, or a writable Python buffer 

376 object. The size to copy, 'n', is always measured in bytes. 

377 

378 Unlike other methods, this one supports all Python buffer including 

379 byte strings and bytearrays---but it still does not support 

380 non-contiguous buffers. 

381 """ 

382 return self._backend.memmove(dest, src, n) 

383 

384 def callback(self, cdecl, python_callable=None, error=None, onerror=None): 

385 """Return a callback object or a decorator making such a 

386 callback object. 'cdecl' must name a C function pointer type. 

387 The callback invokes the specified 'python_callable' (which may 

388 be provided either directly or via a decorator). Important: the 

389 callback object must be manually kept alive for as long as the 

390 callback may be invoked from the C level. 

391 """ 

392 def callback_decorator_wrap(python_callable): 

393 if not callable(python_callable): 

394 raise TypeError("the 'python_callable' argument " 

395 "is not callable") 

396 return self._backend.callback(cdecl, python_callable, 

397 error, onerror) 

398 if isinstance(cdecl, basestring): 

399 cdecl = self._typeof(cdecl, consider_function_as_funcptr=True) 

400 if python_callable is None: 

401 return callback_decorator_wrap # decorator mode 

402 else: 

403 return callback_decorator_wrap(python_callable) # direct mode 

404 

405 def getctype(self, cdecl, replace_with=''): 

406 """Return a string giving the C type 'cdecl', which may be itself 

407 a string or a <ctype> object. If 'replace_with' is given, it gives 

408 extra text to append (or insert for more complicated C types), like 

409 a variable name, or '*' to get actually the C type 'pointer-to-cdecl'. 

410 """ 

411 if isinstance(cdecl, basestring): 

412 cdecl = self._typeof(cdecl) 

413 replace_with = replace_with.strip() 

414 if (replace_with.startswith('*') 

415 and '&[' in self._backend.getcname(cdecl, '&')): 

416 replace_with = '(%s)' % replace_with 

417 elif replace_with and not replace_with[0] in '[(': 

418 replace_with = ' ' + replace_with 

419 return self._backend.getcname(cdecl, replace_with) 

420 

421 def gc(self, cdata, destructor, size=0): 

422 """Return a new cdata object that points to the same 

423 data. Later, when this new cdata object is garbage-collected, 

424 'destructor(old_cdata_object)' will be called. 

425 

426 The optional 'size' gives an estimate of the size, used to 

427 trigger the garbage collection more eagerly. So far only used 

428 on PyPy. It tells the GC that the returned object keeps alive 

429 roughly 'size' bytes of external memory. 

430 """ 

431 return self._backend.gcp(cdata, destructor, size) 

432 

433 def _get_cached_btype(self, type): 

434 assert self._lock.acquire(False) is False 

435 # call me with the lock! 

436 try: 

437 BType = self._cached_btypes[type] 

438 except KeyError: 

439 finishlist = [] 

440 BType = type.get_cached_btype(self, finishlist) 

441 for type in finishlist: 

442 type.finish_backend_type(self, finishlist) 

443 return BType 

444 

445 def verify(self, source='', tmpdir=None, **kwargs): 

446 """Verify that the current ffi signatures compile on this 

447 machine, and return a dynamic library object. The dynamic 

448 library can be used to call functions and access global 

449 variables declared in this 'ffi'. The library is compiled 

450 by the C compiler: it gives you C-level API compatibility 

451 (including calling macros). This is unlike 'ffi.dlopen()', 

452 which requires binary compatibility in the signatures. 

453 """ 

454 from .verifier import Verifier, _caller_dir_pycache 

455 # 

456 # If set_unicode(True) was called, insert the UNICODE and 

457 # _UNICODE macro declarations 

458 if self._windows_unicode: 

459 self._apply_windows_unicode(kwargs) 

460 # 

461 # Set the tmpdir here, and not in Verifier.__init__: it picks 

462 # up the caller's directory, which we want to be the caller of 

463 # ffi.verify(), as opposed to the caller of Veritier(). 

464 tmpdir = tmpdir or _caller_dir_pycache() 

465 # 

466 # Make a Verifier() and use it to load the library. 

467 self.verifier = Verifier(self, source, tmpdir, **kwargs) 

468 lib = self.verifier.load_library() 

469 # 

470 # Save the loaded library for keep-alive purposes, even 

471 # if the caller doesn't keep it alive itself (it should). 

472 self._libraries.append(lib) 

473 return lib 

474 

475 def _get_errno(self): 

476 return self._backend.get_errno() 

477 def _set_errno(self, errno): 

478 self._backend.set_errno(errno) 

479 errno = property(_get_errno, _set_errno, None, 

480 "the value of 'errno' from/to the C calls") 

481 

482 def getwinerror(self, code=-1): 

483 return self._backend.getwinerror(code) 

484 

485 def _pointer_to(self, ctype): 

486 with self._lock: 

487 return model.pointer_cache(self, ctype) 

488 

489 def addressof(self, cdata, *fields_or_indexes): 

490 """Return the address of a <cdata 'struct-or-union'>. 

491 If 'fields_or_indexes' are given, returns the address of that 

492 field or array item in the structure or array, recursively in 

493 case of nested structures. 

494 """ 

495 try: 

496 ctype = self._backend.typeof(cdata) 

497 except TypeError: 

498 if '__addressof__' in type(cdata).__dict__: 

499 return type(cdata).__addressof__(cdata, *fields_or_indexes) 

500 raise 

501 if fields_or_indexes: 

502 ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes) 

503 else: 

504 if ctype.kind == "pointer": 

505 raise TypeError("addressof(pointer)") 

506 offset = 0 

507 ctypeptr = self._pointer_to(ctype) 

508 return self._backend.rawaddressof(ctypeptr, cdata, offset) 

509 

510 def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes): 

511 ctype, offset = self._backend.typeoffsetof(ctype, field_or_index) 

512 for field1 in fields_or_indexes: 

513 ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1) 

514 offset += offset1 

515 return ctype, offset 

516 

517 def include(self, ffi_to_include): 

518 """Includes the typedefs, structs, unions and enums defined 

519 in another FFI instance. Usage is similar to a #include in C, 

520 where a part of the program might include types defined in 

521 another part for its own usage. Note that the include() 

522 method has no effect on functions, constants and global 

523 variables, which must anyway be accessed directly from the 

524 lib object returned by the original FFI instance. 

525 """ 

526 if not isinstance(ffi_to_include, FFI): 

527 raise TypeError("ffi.include() expects an argument that is also of" 

528 " type cffi.FFI, not %r" % ( 

529 type(ffi_to_include).__name__,)) 

530 if ffi_to_include is self: 

531 raise ValueError("self.include(self)") 

532 with ffi_to_include._lock: 

533 with self._lock: 

534 self._parser.include(ffi_to_include._parser) 

535 self._cdefsources.append('[') 

536 self._cdefsources.extend(ffi_to_include._cdefsources) 

537 self._cdefsources.append(']') 

538 self._included_ffis.append(ffi_to_include) 

539 

540 def new_handle(self, x): 

541 return self._backend.newp_handle(self.BVoidP, x) 

542 

543 def from_handle(self, x): 

544 return self._backend.from_handle(x) 

545 

546 def release(self, x): 

547 self._backend.release(x) 

548 

549 def set_unicode(self, enabled_flag): 

550 """Windows: if 'enabled_flag' is True, enable the UNICODE and 

551 _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR 

552 to be (pointers to) wchar_t. If 'enabled_flag' is False, 

553 declare these types to be (pointers to) plain 8-bit characters. 

554 This is mostly for backward compatibility; you usually want True. 

555 """ 

556 if self._windows_unicode is not None: 

557 raise ValueError("set_unicode() can only be called once") 

558 enabled_flag = bool(enabled_flag) 

559 if enabled_flag: 

560 self.cdef("typedef wchar_t TBYTE;" 

561 "typedef wchar_t TCHAR;" 

562 "typedef const wchar_t *LPCTSTR;" 

563 "typedef const wchar_t *PCTSTR;" 

564 "typedef wchar_t *LPTSTR;" 

565 "typedef wchar_t *PTSTR;" 

566 "typedef TBYTE *PTBYTE;" 

567 "typedef TCHAR *PTCHAR;") 

568 else: 

569 self.cdef("typedef char TBYTE;" 

570 "typedef char TCHAR;" 

571 "typedef const char *LPCTSTR;" 

572 "typedef const char *PCTSTR;" 

573 "typedef char *LPTSTR;" 

574 "typedef char *PTSTR;" 

575 "typedef TBYTE *PTBYTE;" 

576 "typedef TCHAR *PTCHAR;") 

577 self._windows_unicode = enabled_flag 

578 

579 def _apply_windows_unicode(self, kwds): 

580 defmacros = kwds.get('define_macros', ()) 

581 if not isinstance(defmacros, (list, tuple)): 

582 raise TypeError("'define_macros' must be a list or tuple") 

583 defmacros = list(defmacros) + [('UNICODE', '1'), 

584 ('_UNICODE', '1')] 

585 kwds['define_macros'] = defmacros 

586 

587 def _apply_embedding_fix(self, kwds): 

588 # must include an argument like "-lpython2.7" for the compiler 

589 def ensure(key, value): 

590 lst = kwds.setdefault(key, []) 

591 if value not in lst: 

592 lst.append(value) 

593 # 

594 if '__pypy__' in sys.builtin_module_names: 

595 import os 

596 if sys.platform == "win32": 

597 # we need 'libpypy-c.lib'. Current distributions of 

598 # pypy (>= 4.1) contain it as 'libs/python27.lib'. 

599 pythonlib = "python{0[0]}{0[1]}".format(sys.version_info) 

600 if hasattr(sys, 'prefix'): 

601 ensure('library_dirs', os.path.join(sys.prefix, 'libs')) 

602 else: 

603 # we need 'libpypy-c.{so,dylib}', which should be by 

604 # default located in 'sys.prefix/bin' for installed 

605 # systems. 

606 if sys.version_info < (3,): 

607 pythonlib = "pypy-c" 

608 else: 

609 pythonlib = "pypy3-c" 

610 if hasattr(sys, 'prefix'): 

611 ensure('library_dirs', os.path.join(sys.prefix, 'bin')) 

612 # On uninstalled pypy's, the libpypy-c is typically found in 

613 # .../pypy/goal/. 

614 if hasattr(sys, 'prefix'): 

615 ensure('library_dirs', os.path.join(sys.prefix, 'pypy', 'goal')) 

616 else: 

617 if sys.platform == "win32": 

618 template = "python%d%d" 

619 if hasattr(sys, 'gettotalrefcount'): 

620 template += '_d' 

621 else: 

622 try: 

623 import sysconfig 

624 except ImportError: # 2.6 

625 from distutils import sysconfig 

626 template = "python%d.%d" 

627 if sysconfig.get_config_var('DEBUG_EXT'): 

628 template += sysconfig.get_config_var('DEBUG_EXT') 

629 pythonlib = (template % 

630 (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) 

631 if hasattr(sys, 'abiflags'): 

632 pythonlib += sys.abiflags 

633 ensure('libraries', pythonlib) 

634 if sys.platform == "win32": 

635 ensure('extra_link_args', '/MANIFEST') 

636 

637 def set_source(self, module_name, source, source_extension='.c', **kwds): 

638 import os 

639 if hasattr(self, '_assigned_source'): 

640 raise ValueError("set_source() cannot be called several times " 

641 "per ffi object") 

642 if not isinstance(module_name, basestring): 

643 raise TypeError("'module_name' must be a string") 

644 if os.sep in module_name or (os.altsep and os.altsep in module_name): 

645 raise ValueError("'module_name' must not contain '/': use a dotted " 

646 "name to make a 'package.module' location") 

647 self._assigned_source = (str(module_name), source, 

648 source_extension, kwds) 

649 

650 def set_source_pkgconfig(self, module_name, pkgconfig_libs, source, 

651 source_extension='.c', **kwds): 

652 from . import pkgconfig 

653 if not isinstance(pkgconfig_libs, list): 

654 raise TypeError("the pkgconfig_libs argument must be a list " 

655 "of package names") 

656 kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs) 

657 pkgconfig.merge_flags(kwds, kwds2) 

658 self.set_source(module_name, source, source_extension, **kwds) 

659 

660 def distutils_extension(self, tmpdir='build', verbose=True): 

661 from distutils.dir_util import mkpath 

662 from .recompiler import recompile 

663 # 

664 if not hasattr(self, '_assigned_source'): 

665 if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored 

666 return self.verifier.get_extension() 

667 raise ValueError("set_source() must be called before" 

668 " distutils_extension()") 

669 module_name, source, source_extension, kwds = self._assigned_source 

670 if source is None: 

671 raise TypeError("distutils_extension() is only for C extension " 

672 "modules, not for dlopen()-style pure Python " 

673 "modules") 

674 mkpath(tmpdir) 

675 ext, updated = recompile(self, module_name, 

676 source, tmpdir=tmpdir, extradir=tmpdir, 

677 source_extension=source_extension, 

678 call_c_compiler=False, **kwds) 

679 if verbose: 

680 if updated: 

681 sys.stderr.write("regenerated: %r\n" % (ext.sources[0],)) 

682 else: 

683 sys.stderr.write("not modified: %r\n" % (ext.sources[0],)) 

684 return ext 

685 

686 def emit_c_code(self, filename): 

687 from .recompiler import recompile 

688 # 

689 if not hasattr(self, '_assigned_source'): 

690 raise ValueError("set_source() must be called before emit_c_code()") 

691 module_name, source, source_extension, kwds = self._assigned_source 

692 if source is None: 

693 raise TypeError("emit_c_code() is only for C extension modules, " 

694 "not for dlopen()-style pure Python modules") 

695 recompile(self, module_name, source, 

696 c_file=filename, call_c_compiler=False, **kwds) 

697 

698 def emit_python_code(self, filename): 

699 from .recompiler import recompile 

700 # 

701 if not hasattr(self, '_assigned_source'): 

702 raise ValueError("set_source() must be called before emit_c_code()") 

703 module_name, source, source_extension, kwds = self._assigned_source 

704 if source is not None: 

705 raise TypeError("emit_python_code() is only for dlopen()-style " 

706 "pure Python modules, not for C extension modules") 

707 recompile(self, module_name, source, 

708 c_file=filename, call_c_compiler=False, **kwds) 

709 

710 def compile(self, tmpdir='.', verbose=0, target=None, debug=None): 

711 """The 'target' argument gives the final file name of the 

712 compiled DLL. Use '*' to force distutils' choice, suitable for 

713 regular CPython C API modules. Use a file name ending in '.*' 

714 to ask for the system's default extension for dynamic libraries 

715 (.so/.dll/.dylib). 

716 

717 The default is '*' when building a non-embedded C API extension, 

718 and (module_name + '.*') when building an embedded library. 

719 """ 

720 from .recompiler import recompile 

721 # 

722 if not hasattr(self, '_assigned_source'): 

723 raise ValueError("set_source() must be called before compile()") 

724 module_name, source, source_extension, kwds = self._assigned_source 

725 return recompile(self, module_name, source, tmpdir=tmpdir, 

726 target=target, source_extension=source_extension, 

727 compiler_verbose=verbose, debug=debug, **kwds) 

728 

729 def init_once(self, func, tag): 

730 # Read _init_once_cache[tag], which is either (False, lock) if 

731 # we're calling the function now in some thread, or (True, result). 

732 # Don't call setdefault() in most cases, to avoid allocating and 

733 # immediately freeing a lock; but still use setdefaut() to avoid 

734 # races. 

735 try: 

736 x = self._init_once_cache[tag] 

737 except KeyError: 

738 x = self._init_once_cache.setdefault(tag, (False, allocate_lock())) 

739 # Common case: we got (True, result), so we return the result. 

740 if x[0]: 

741 return x[1] 

742 # Else, it's a lock. Acquire it to serialize the following tests. 

743 with x[1]: 

744 # Read again from _init_once_cache the current status. 

745 x = self._init_once_cache[tag] 

746 if x[0]: 

747 return x[1] 

748 # Call the function and store the result back. 

749 result = func() 

750 self._init_once_cache[tag] = (True, result) 

751 return result 

752 

753 def embedding_init_code(self, pysource): 

754 if self._embedding: 

755 raise ValueError("embedding_init_code() can only be called once") 

756 # fix 'pysource' before it gets dumped into the C file: 

757 # - remove empty lines at the beginning, so it starts at "line 1" 

758 # - dedent, if all non-empty lines are indented 

759 # - check for SyntaxErrors 

760 import re 

761 match = re.match(r'\s*\n', pysource) 

762 if match: 

763 pysource = pysource[match.end():] 

764 lines = pysource.splitlines() or [''] 

765 prefix = re.match(r'\s*', lines[0]).group() 

766 for i in range(1, len(lines)): 

767 line = lines[i] 

768 if line.rstrip(): 

769 while not line.startswith(prefix): 

770 prefix = prefix[:-1] 

771 i = len(prefix) 

772 lines = [line[i:]+'\n' for line in lines] 

773 pysource = ''.join(lines) 

774 # 

775 compile(pysource, "cffi_init", "exec") 

776 # 

777 self._embedding = pysource 

778 

779 def def_extern(self, *args, **kwds): 

780 raise ValueError("ffi.def_extern() is only available on API-mode FFI " 

781 "objects") 

782 

783 def list_types(self): 

784 """Returns the user type names known to this FFI instance. 

785 This returns a tuple containing three lists of names: 

786 (typedef_names, names_of_structs, names_of_unions) 

787 """ 

788 typedefs = [] 

789 structs = [] 

790 unions = [] 

791 for key in self._parser._declarations: 

792 if key.startswith('typedef '): 

793 typedefs.append(key[8:]) 

794 elif key.startswith('struct '): 

795 structs.append(key[7:]) 

796 elif key.startswith('union '): 

797 unions.append(key[6:]) 

798 typedefs.sort() 

799 structs.sort() 

800 unions.sort() 

801 return (typedefs, structs, unions) 

802 

803 

804def _load_backend_lib(backend, name, flags): 

805 import os 

806 if not isinstance(name, basestring): 

807 if sys.platform != "win32" or name is not None: 

808 return backend.load_library(name, flags) 

809 name = "c" # Windows: load_library(None) fails, but this works 

810 # on Python 2 (backward compatibility hack only) 

811 first_error = None 

812 if '.' in name or '/' in name or os.sep in name: 

813 try: 

814 return backend.load_library(name, flags) 

815 except OSError as e: 

816 first_error = e 

817 import ctypes.util 

818 path = ctypes.util.find_library(name) 

819 if path is None: 

820 if name == "c" and sys.platform == "win32" and sys.version_info >= (3,): 

821 raise OSError("dlopen(None) cannot work on Windows for Python 3 " 

822 "(see http://bugs.python.org/issue23606)") 

823 msg = ("ctypes.util.find_library() did not manage " 

824 "to locate a library called %r" % (name,)) 

825 if first_error is not None: 

826 msg = "%s. Additionally, %s" % (first_error, msg) 

827 raise OSError(msg) 

828 return backend.load_library(path, flags) 

829 

830def _make_ffi_library(ffi, libname, flags): 

831 backend = ffi._backend 

832 backendlib = _load_backend_lib(backend, libname, flags) 

833 # 

834 def accessor_function(name): 

835 key = 'function ' + name 

836 tp, _ = ffi._parser._declarations[key] 

837 BType = ffi._get_cached_btype(tp) 

838 value = backendlib.load_function(BType, name) 

839 library.__dict__[name] = value 

840 # 

841 def accessor_variable(name): 

842 key = 'variable ' + name 

843 tp, _ = ffi._parser._declarations[key] 

844 BType = ffi._get_cached_btype(tp) 

845 read_variable = backendlib.read_variable 

846 write_variable = backendlib.write_variable 

847 setattr(FFILibrary, name, property( 

848 lambda self: read_variable(BType, name), 

849 lambda self, value: write_variable(BType, name, value))) 

850 # 

851 def addressof_var(name): 

852 try: 

853 return addr_variables[name] 

854 except KeyError: 

855 with ffi._lock: 

856 if name not in addr_variables: 

857 key = 'variable ' + name 

858 tp, _ = ffi._parser._declarations[key] 

859 BType = ffi._get_cached_btype(tp) 

860 if BType.kind != 'array': 

861 BType = model.pointer_cache(ffi, BType) 

862 p = backendlib.load_function(BType, name) 

863 addr_variables[name] = p 

864 return addr_variables[name] 

865 # 

866 def accessor_constant(name): 

867 raise NotImplementedError("non-integer constant '%s' cannot be " 

868 "accessed from a dlopen() library" % (name,)) 

869 # 

870 def accessor_int_constant(name): 

871 library.__dict__[name] = ffi._parser._int_constants[name] 

872 # 

873 accessors = {} 

874 accessors_version = [False] 

875 addr_variables = {} 

876 # 

877 def update_accessors(): 

878 if accessors_version[0] is ffi._cdef_version: 

879 return 

880 # 

881 for key, (tp, _) in ffi._parser._declarations.items(): 

882 if not isinstance(tp, model.EnumType): 

883 tag, name = key.split(' ', 1) 

884 if tag == 'function': 

885 accessors[name] = accessor_function 

886 elif tag == 'variable': 

887 accessors[name] = accessor_variable 

888 elif tag == 'constant': 

889 accessors[name] = accessor_constant 

890 else: 

891 for i, enumname in enumerate(tp.enumerators): 

892 def accessor_enum(name, tp=tp, i=i): 

893 tp.check_not_partial() 

894 library.__dict__[name] = tp.enumvalues[i] 

895 accessors[enumname] = accessor_enum 

896 for name in ffi._parser._int_constants: 

897 accessors.setdefault(name, accessor_int_constant) 

898 accessors_version[0] = ffi._cdef_version 

899 # 

900 def make_accessor(name): 

901 with ffi._lock: 

902 if name in library.__dict__ or name in FFILibrary.__dict__: 

903 return # added by another thread while waiting for the lock 

904 if name not in accessors: 

905 update_accessors() 

906 if name not in accessors: 

907 raise AttributeError(name) 

908 accessors[name](name) 

909 # 

910 class FFILibrary(object): 

911 def __getattr__(self, name): 

912 make_accessor(name) 

913 return getattr(self, name) 

914 def __setattr__(self, name, value): 

915 try: 

916 property = getattr(self.__class__, name) 

917 except AttributeError: 

918 make_accessor(name) 

919 setattr(self, name, value) 

920 else: 

921 property.__set__(self, value) 

922 def __dir__(self): 

923 with ffi._lock: 

924 update_accessors() 

925 return accessors.keys() 

926 def __addressof__(self, name): 

927 if name in library.__dict__: 

928 return library.__dict__[name] 

929 if name in FFILibrary.__dict__: 

930 return addressof_var(name) 

931 make_accessor(name) 

932 if name in library.__dict__: 

933 return library.__dict__[name] 

934 if name in FFILibrary.__dict__: 

935 return addressof_var(name) 

936 raise AttributeError("cffi library has no function or " 

937 "global variable named '%s'" % (name,)) 

938 def __cffi_close__(self): 

939 backendlib.close_lib() 

940 self.__dict__.clear() 

941 # 

942 if isinstance(libname, basestring): 

943 try: 

944 if not isinstance(libname, str): # unicode, on Python 2 

945 libname = libname.encode('utf-8') 

946 FFILibrary.__name__ = 'FFILibrary_%s' % libname 

947 except UnicodeError: 

948 pass 

949 library = FFILibrary() 

950 return library, library.__dict__ 

951 

952def _builtin_function_type(func): 

953 # a hack to make at least ffi.typeof(builtin_function) work, 

954 # if the builtin function was obtained by 'vengine_cpy'. 

955 import sys 

956 try: 

957 module = sys.modules[func.__module__] 

958 ffi = module._cffi_original_ffi 

959 types_of_builtin_funcs = module._cffi_types_of_builtin_funcs 

960 tp = types_of_builtin_funcs[func] 

961 except (KeyError, AttributeError, TypeError): 

962 return None 

963 else: 

964 with ffi._lock: 

965 return ffi._get_cached_btype(tp)