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 assert isinstance(name, basestring) or name is None 145 with self._lock: 146 lib, function_cache = _make_ffi_library(self, name, flags) 147 self._function_caches.append(function_cache) 148 self._libraries.append(lib) 149 return lib 150 151 def dlclose(self, lib): 152 """Close a library obtained with ffi.dlopen(). After this call, 153 access to functions or variables from the library will fail 154 (possibly with a segmentation fault). 155 """ 156 type(lib).__cffi_close__(lib) 157 158 def _typeof_locked(self, cdecl): 159 # call me with the lock! 160 key = cdecl 161 if key in self._parsed_types: 162 return self._parsed_types[key] 163 # 164 if not isinstance(cdecl, str): # unicode, on Python 2 165 cdecl = cdecl.encode('ascii') 166 # 167 type = self._parser.parse_type(cdecl) 168 really_a_function_type = type.is_raw_function 169 if really_a_function_type: 170 type = type.as_function_pointer() 171 btype = self._get_cached_btype(type) 172 result = btype, really_a_function_type 173 self._parsed_types[key] = result 174 return result 175 176 def _typeof(self, cdecl, consider_function_as_funcptr=False): 177 # string -> ctype object 178 try: 179 result = self._parsed_types[cdecl] 180 except KeyError: 181 with self._lock: 182 result = self._typeof_locked(cdecl) 183 # 184 btype, really_a_function_type = result 185 if really_a_function_type and not consider_function_as_funcptr: 186 raise CDefError("the type %r is a function type, not a " 187 "pointer-to-function type" % (cdecl,)) 188 return btype 189 190 def typeof(self, cdecl): 191 """Parse the C type given as a string and return the 192 corresponding <ctype> object. 193 It can also be used on 'cdata' instance to get its C type. 194 """ 195 if isinstance(cdecl, basestring): 196 return self._typeof(cdecl) 197 if isinstance(cdecl, self.CData): 198 return self._backend.typeof(cdecl) 199 if isinstance(cdecl, types.BuiltinFunctionType): 200 res = _builtin_function_type(cdecl) 201 if res is not None: 202 return res 203 if (isinstance(cdecl, types.FunctionType) 204 and hasattr(cdecl, '_cffi_base_type')): 205 with self._lock: 206 return self._get_cached_btype(cdecl._cffi_base_type) 207 raise TypeError(type(cdecl)) 208 209 def sizeof(self, cdecl): 210 """Return the size in bytes of the argument. It can be a 211 string naming a C type, or a 'cdata' instance. 212 """ 213 if isinstance(cdecl, basestring): 214 BType = self._typeof(cdecl) 215 return self._backend.sizeof(BType) 216 else: 217 return self._backend.sizeof(cdecl) 218 219 def alignof(self, cdecl): 220 """Return the natural alignment size in bytes of the C type 221 given as a string. 222 """ 223 if isinstance(cdecl, basestring): 224 cdecl = self._typeof(cdecl) 225 return self._backend.alignof(cdecl) 226 227 def offsetof(self, cdecl, *fields_or_indexes): 228 """Return the offset of the named field inside the given 229 structure or array, which must be given as a C type name. 230 You can give several field names in case of nested structures. 231 You can also give numeric values which correspond to array 232 items, in case of an array type. 233 """ 234 if isinstance(cdecl, basestring): 235 cdecl = self._typeof(cdecl) 236 return self._typeoffsetof(cdecl, *fields_or_indexes)[1] 237 238 def new(self, cdecl, init=None): 239 """Allocate an instance according to the specified C type and 240 return a pointer to it. The specified C type must be either a 241 pointer or an array: ``new('X *')`` allocates an X and returns 242 a pointer to it, whereas ``new('X[n]')`` allocates an array of 243 n X'es and returns an array referencing it (which works 244 mostly like a pointer, like in C). You can also use 245 ``new('X[]', n)`` to allocate an array of a non-constant 246 length n. 247 248 The memory is initialized following the rules of declaring a 249 global variable in C: by default it is zero-initialized, but 250 an explicit initializer can be given which can be used to 251 fill all or part of the memory. 252 253 When the returned <cdata> object goes out of scope, the memory 254 is freed. In other words the returned <cdata> object has 255 ownership of the value of type 'cdecl' that it points to. This 256 means that the raw data can be used as long as this object is 257 kept alive, but must not be used for a longer time. Be careful 258 about that when copying the pointer to the memory somewhere 259 else, e.g. into another structure. 260 """ 261 if isinstance(cdecl, basestring): 262 cdecl = self._typeof(cdecl) 263 return self._backend.newp(cdecl, init) 264 265 def new_allocator(self, alloc=None, free=None, 266 should_clear_after_alloc=True): 267 """Return a new allocator, i.e. a function that behaves like ffi.new() 268 but uses the provided low-level 'alloc' and 'free' functions. 269 270 'alloc' is called with the size as argument. If it returns NULL, a 271 MemoryError is raised. 'free' is called with the result of 'alloc' 272 as argument. Both can be either Python function or directly C 273 functions. If 'free' is None, then no free function is called. 274 If both 'alloc' and 'free' are None, the default is used. 275 276 If 'should_clear_after_alloc' is set to False, then the memory 277 returned by 'alloc' is assumed to be already cleared (or you are 278 fine with garbage); otherwise CFFI will clear it. 279 """ 280 compiled_ffi = self._backend.FFI() 281 allocator = compiled_ffi.new_allocator(alloc, free, 282 should_clear_after_alloc) 283 def allocate(cdecl, init=None): 284 if isinstance(cdecl, basestring): 285 cdecl = self._typeof(cdecl) 286 return allocator(cdecl, init) 287 return allocate 288 289 def cast(self, cdecl, source): 290 """Similar to a C cast: returns an instance of the named C 291 type initialized with the given 'source'. The source is 292 casted between integers or pointers of any type. 293 """ 294 if isinstance(cdecl, basestring): 295 cdecl = self._typeof(cdecl) 296 return self._backend.cast(cdecl, source) 297 298 def string(self, cdata, maxlen=-1): 299 """Return a Python string (or unicode string) from the 'cdata'. 300 If 'cdata' is a pointer or array of characters or bytes, returns 301 the null-terminated string. The returned string extends until 302 the first null character, or at most 'maxlen' characters. If 303 'cdata' is an array then 'maxlen' defaults to its length. 304 305 If 'cdata' is a pointer or array of wchar_t, returns a unicode 306 string following the same rules. 307 308 If 'cdata' is a single character or byte or a wchar_t, returns 309 it as a string or unicode string. 310 311 If 'cdata' is an enum, returns the value of the enumerator as a 312 string, or 'NUMBER' if the value is out of range. 313 """ 314 return self._backend.string(cdata, maxlen) 315 316 def unpack(self, cdata, length): 317 """Unpack an array of C data of the given length, 318 returning a Python string/unicode/list. 319 320 If 'cdata' is a pointer to 'char', returns a byte string. 321 It does not stop at the first null. This is equivalent to: 322 ffi.buffer(cdata, length)[:] 323 324 If 'cdata' is a pointer to 'wchar_t', returns a unicode string. 325 'length' is measured in wchar_t's; it is not the size in bytes. 326 327 If 'cdata' is a pointer to anything else, returns a list of 328 'length' items. This is a faster equivalent to: 329 [cdata[i] for i in range(length)] 330 """ 331 return self._backend.unpack(cdata, length) 332 333 #def buffer(self, cdata, size=-1): 334 # """Return a read-write buffer object that references the raw C data 335 # pointed to by the given 'cdata'. The 'cdata' must be a pointer or 336 # an array. Can be passed to functions expecting a buffer, or directly 337 # manipulated with: 338 # 339 # buf[:] get a copy of it in a regular string, or 340 # buf[idx] as a single character 341 # buf[:] = ... 342 # buf[idx] = ... change the content 343 # """ 344 # note that 'buffer' is a type, set on this instance by __init__ 345 346 def from_buffer(self, cdecl, python_buffer=_unspecified, 347 require_writable=False): 348 """Return a cdata of the given type pointing to the data of the 349 given Python object, which must support the buffer interface. 350 Note that this is not meant to be used on the built-in types 351 str or unicode (you can build 'char[]' arrays explicitly) 352 but only on objects containing large quantities of raw data 353 in some other format, like 'array.array' or numpy arrays. 354 355 The first argument is optional and default to 'char[]'. 356 """ 357 if python_buffer is _unspecified: 358 cdecl, python_buffer = self.BCharA, cdecl 359 elif isinstance(cdecl, basestring): 360 cdecl = self._typeof(cdecl) 361 return self._backend.from_buffer(cdecl, python_buffer, 362 require_writable) 363 364 def memmove(self, dest, src, n): 365 """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest. 366 367 Like the C function memmove(), the memory areas may overlap; 368 apart from that it behaves like the C function memcpy(). 369 370 'src' can be any cdata ptr or array, or any Python buffer object. 371 'dest' can be any cdata ptr or array, or a writable Python buffer 372 object. The size to copy, 'n', is always measured in bytes. 373 374 Unlike other methods, this one supports all Python buffer including 375 byte strings and bytearrays---but it still does not support 376 non-contiguous buffers. 377 """ 378 return self._backend.memmove(dest, src, n) 379 380 def callback(self, cdecl, python_callable=None, error=None, onerror=None): 381 """Return a callback object or a decorator making such a 382 callback object. 'cdecl' must name a C function pointer type. 383 The callback invokes the specified 'python_callable' (which may 384 be provided either directly or via a decorator). Important: the 385 callback object must be manually kept alive for as long as the 386 callback may be invoked from the C level. 387 """ 388 def callback_decorator_wrap(python_callable): 389 if not callable(python_callable): 390 raise TypeError("the 'python_callable' argument " 391 "is not callable") 392 return self._backend.callback(cdecl, python_callable, 393 error, onerror) 394 if isinstance(cdecl, basestring): 395 cdecl = self._typeof(cdecl, consider_function_as_funcptr=True) 396 if python_callable is None: 397 return callback_decorator_wrap # decorator mode 398 else: 399 return callback_decorator_wrap(python_callable) # direct mode 400 401 def getctype(self, cdecl, replace_with=''): 402 """Return a string giving the C type 'cdecl', which may be itself 403 a string or a <ctype> object. If 'replace_with' is given, it gives 404 extra text to append (or insert for more complicated C types), like 405 a variable name, or '*' to get actually the C type 'pointer-to-cdecl'. 406 """ 407 if isinstance(cdecl, basestring): 408 cdecl = self._typeof(cdecl) 409 replace_with = replace_with.strip() 410 if (replace_with.startswith('*') 411 and '&[' in self._backend.getcname(cdecl, '&')): 412 replace_with = '(%s)' % replace_with 413 elif replace_with and not replace_with[0] in '[(': 414 replace_with = ' ' + replace_with 415 return self._backend.getcname(cdecl, replace_with) 416 417 def gc(self, cdata, destructor, size=0): 418 """Return a new cdata object that points to the same 419 data. Later, when this new cdata object is garbage-collected, 420 'destructor(old_cdata_object)' will be called. 421 422 The optional 'size' gives an estimate of the size, used to 423 trigger the garbage collection more eagerly. So far only used 424 on PyPy. It tells the GC that the returned object keeps alive 425 roughly 'size' bytes of external memory. 426 """ 427 return self._backend.gcp(cdata, destructor, size) 428 429 def _get_cached_btype(self, type): 430 assert self._lock.acquire(False) is False 431 # call me with the lock! 432 try: 433 BType = self._cached_btypes[type] 434 except KeyError: 435 finishlist = [] 436 BType = type.get_cached_btype(self, finishlist) 437 for type in finishlist: 438 type.finish_backend_type(self, finishlist) 439 return BType 440 441 def verify(self, source='', tmpdir=None, **kwargs): 442 """Verify that the current ffi signatures compile on this 443 machine, and return a dynamic library object. The dynamic 444 library can be used to call functions and access global 445 variables declared in this 'ffi'. The library is compiled 446 by the C compiler: it gives you C-level API compatibility 447 (including calling macros). This is unlike 'ffi.dlopen()', 448 which requires binary compatibility in the signatures. 449 """ 450 from .verifier import Verifier, _caller_dir_pycache 451 # 452 # If set_unicode(True) was called, insert the UNICODE and 453 # _UNICODE macro declarations 454 if self._windows_unicode: 455 self._apply_windows_unicode(kwargs) 456 # 457 # Set the tmpdir here, and not in Verifier.__init__: it picks 458 # up the caller's directory, which we want to be the caller of 459 # ffi.verify(), as opposed to the caller of Veritier(). 460 tmpdir = tmpdir or _caller_dir_pycache() 461 # 462 # Make a Verifier() and use it to load the library. 463 self.verifier = Verifier(self, source, tmpdir, **kwargs) 464 lib = self.verifier.load_library() 465 # 466 # Save the loaded library for keep-alive purposes, even 467 # if the caller doesn't keep it alive itself (it should). 468 self._libraries.append(lib) 469 return lib 470 471 def _get_errno(self): 472 return self._backend.get_errno() 473 def _set_errno(self, errno): 474 self._backend.set_errno(errno) 475 errno = property(_get_errno, _set_errno, None, 476 "the value of 'errno' from/to the C calls") 477 478 def getwinerror(self, code=-1): 479 return self._backend.getwinerror(code) 480 481 def _pointer_to(self, ctype): 482 with self._lock: 483 return model.pointer_cache(self, ctype) 484 485 def addressof(self, cdata, *fields_or_indexes): 486 """Return the address of a <cdata 'struct-or-union'>. 487 If 'fields_or_indexes' are given, returns the address of that 488 field or array item in the structure or array, recursively in 489 case of nested structures. 490 """ 491 try: 492 ctype = self._backend.typeof(cdata) 493 except TypeError: 494 if '__addressof__' in type(cdata).__dict__: 495 return type(cdata).__addressof__(cdata, *fields_or_indexes) 496 raise 497 if fields_or_indexes: 498 ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes) 499 else: 500 if ctype.kind == "pointer": 501 raise TypeError("addressof(pointer)") 502 offset = 0 503 ctypeptr = self._pointer_to(ctype) 504 return self._backend.rawaddressof(ctypeptr, cdata, offset) 505 506 def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes): 507 ctype, offset = self._backend.typeoffsetof(ctype, field_or_index) 508 for field1 in fields_or_indexes: 509 ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1) 510 offset += offset1 511 return ctype, offset 512 513 def include(self, ffi_to_include): 514 """Includes the typedefs, structs, unions and enums defined 515 in another FFI instance. Usage is similar to a #include in C, 516 where a part of the program might include types defined in 517 another part for its own usage. Note that the include() 518 method has no effect on functions, constants and global 519 variables, which must anyway be accessed directly from the 520 lib object returned by the original FFI instance. 521 """ 522 if not isinstance(ffi_to_include, FFI): 523 raise TypeError("ffi.include() expects an argument that is also of" 524 " type cffi.FFI, not %r" % ( 525 type(ffi_to_include).__name__,)) 526 if ffi_to_include is self: 527 raise ValueError("self.include(self)") 528 with ffi_to_include._lock: 529 with self._lock: 530 self._parser.include(ffi_to_include._parser) 531 self._cdefsources.append('[') 532 self._cdefsources.extend(ffi_to_include._cdefsources) 533 self._cdefsources.append(']') 534 self._included_ffis.append(ffi_to_include) 535 536 def new_handle(self, x): 537 return self._backend.newp_handle(self.BVoidP, x) 538 539 def from_handle(self, x): 540 return self._backend.from_handle(x) 541 542 def release(self, x): 543 self._backend.release(x) 544 545 def set_unicode(self, enabled_flag): 546 """Windows: if 'enabled_flag' is True, enable the UNICODE and 547 _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR 548 to be (pointers to) wchar_t. If 'enabled_flag' is False, 549 declare these types to be (pointers to) plain 8-bit characters. 550 This is mostly for backward compatibility; you usually want True. 551 """ 552 if self._windows_unicode is not None: 553 raise ValueError("set_unicode() can only be called once") 554 enabled_flag = bool(enabled_flag) 555 if enabled_flag: 556 self.cdef("typedef wchar_t TBYTE;" 557 "typedef wchar_t TCHAR;" 558 "typedef const wchar_t *LPCTSTR;" 559 "typedef const wchar_t *PCTSTR;" 560 "typedef wchar_t *LPTSTR;" 561 "typedef wchar_t *PTSTR;" 562 "typedef TBYTE *PTBYTE;" 563 "typedef TCHAR *PTCHAR;") 564 else: 565 self.cdef("typedef char TBYTE;" 566 "typedef char TCHAR;" 567 "typedef const char *LPCTSTR;" 568 "typedef const char *PCTSTR;" 569 "typedef char *LPTSTR;" 570 "typedef char *PTSTR;" 571 "typedef TBYTE *PTBYTE;" 572 "typedef TCHAR *PTCHAR;") 573 self._windows_unicode = enabled_flag 574 575 def _apply_windows_unicode(self, kwds): 576 defmacros = kwds.get('define_macros', ()) 577 if not isinstance(defmacros, (list, tuple)): 578 raise TypeError("'define_macros' must be a list or tuple") 579 defmacros = list(defmacros) + [('UNICODE', '1'), 580 ('_UNICODE', '1')] 581 kwds['define_macros'] = defmacros 582 583 def _apply_embedding_fix(self, kwds): 584 # must include an argument like "-lpython2.7" for the compiler 585 def ensure(key, value): 586 lst = kwds.setdefault(key, []) 587 if value not in lst: 588 lst.append(value) 589 # 590 if '__pypy__' in sys.builtin_module_names: 591 import os 592 if sys.platform == "win32": 593 # we need 'libpypy-c.lib'. Current distributions of 594 # pypy (>= 4.1) contain it as 'libs/python27.lib'. 595 pythonlib = "python{0[0]}{0[1]}".format(sys.version_info) 596 if hasattr(sys, 'prefix'): 597 ensure('library_dirs', os.path.join(sys.prefix, 'libs')) 598 else: 599 # we need 'libpypy-c.{so,dylib}', which should be by 600 # default located in 'sys.prefix/bin' for installed 601 # systems. 602 if sys.version_info < (3,): 603 pythonlib = "pypy-c" 604 else: 605 pythonlib = "pypy3-c" 606 if hasattr(sys, 'prefix'): 607 ensure('library_dirs', os.path.join(sys.prefix, 'bin')) 608 # On uninstalled pypy's, the libpypy-c is typically found in 609 # .../pypy/goal/. 610 if hasattr(sys, 'prefix'): 611 ensure('library_dirs', os.path.join(sys.prefix, 'pypy', 'goal')) 612 else: 613 if sys.platform == "win32": 614 template = "python%d%d" 615 if hasattr(sys, 'gettotalrefcount'): 616 template += '_d' 617 else: 618 try: 619 import sysconfig 620 except ImportError: # 2.6 621 from distutils import sysconfig 622 template = "python%d.%d" 623 if sysconfig.get_config_var('DEBUG_EXT'): 624 template += sysconfig.get_config_var('DEBUG_EXT') 625 pythonlib = (template % 626 (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) 627 if hasattr(sys, 'abiflags'): 628 pythonlib += sys.abiflags 629 ensure('libraries', pythonlib) 630 if sys.platform == "win32": 631 ensure('extra_link_args', '/MANIFEST') 632 633 def set_source(self, module_name, source, source_extension='.c', **kwds): 634 import os 635 if hasattr(self, '_assigned_source'): 636 raise ValueError("set_source() cannot be called several times " 637 "per ffi object") 638 if not isinstance(module_name, basestring): 639 raise TypeError("'module_name' must be a string") 640 if os.sep in module_name or (os.altsep and os.altsep in module_name): 641 raise ValueError("'module_name' must not contain '/': use a dotted " 642 "name to make a 'package.module' location") 643 self._assigned_source = (str(module_name), source, 644 source_extension, kwds) 645 646 def set_source_pkgconfig(self, module_name, pkgconfig_libs, source, 647 source_extension='.c', **kwds): 648 from . import pkgconfig 649 if not isinstance(pkgconfig_libs, list): 650 raise TypeError("the pkgconfig_libs argument must be a list " 651 "of package names") 652 kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs) 653 pkgconfig.merge_flags(kwds, kwds2) 654 self.set_source(module_name, source, source_extension, **kwds) 655 656 def distutils_extension(self, tmpdir='build', verbose=True): 657 from distutils.dir_util import mkpath 658 from .recompiler import recompile 659 # 660 if not hasattr(self, '_assigned_source'): 661 if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored 662 return self.verifier.get_extension() 663 raise ValueError("set_source() must be called before" 664 " distutils_extension()") 665 module_name, source, source_extension, kwds = self._assigned_source 666 if source is None: 667 raise TypeError("distutils_extension() is only for C extension " 668 "modules, not for dlopen()-style pure Python " 669 "modules") 670 mkpath(tmpdir) 671 ext, updated = recompile(self, module_name, 672 source, tmpdir=tmpdir, extradir=tmpdir, 673 source_extension=source_extension, 674 call_c_compiler=False, **kwds) 675 if verbose: 676 if updated: 677 sys.stderr.write("regenerated: %r\n" % (ext.sources[0],)) 678 else: 679 sys.stderr.write("not modified: %r\n" % (ext.sources[0],)) 680 return ext 681 682 def emit_c_code(self, filename): 683 from .recompiler import recompile 684 # 685 if not hasattr(self, '_assigned_source'): 686 raise ValueError("set_source() must be called before emit_c_code()") 687 module_name, source, source_extension, kwds = self._assigned_source 688 if source is None: 689 raise TypeError("emit_c_code() is only for C extension modules, " 690 "not for dlopen()-style pure Python modules") 691 recompile(self, module_name, source, 692 c_file=filename, call_c_compiler=False, **kwds) 693 694 def emit_python_code(self, filename): 695 from .recompiler import recompile 696 # 697 if not hasattr(self, '_assigned_source'): 698 raise ValueError("set_source() must be called before emit_c_code()") 699 module_name, source, source_extension, kwds = self._assigned_source 700 if source is not None: 701 raise TypeError("emit_python_code() is only for dlopen()-style " 702 "pure Python modules, not for C extension modules") 703 recompile(self, module_name, source, 704 c_file=filename, call_c_compiler=False, **kwds) 705 706 def compile(self, tmpdir='.', verbose=0, target=None, debug=None): 707 """The 'target' argument gives the final file name of the 708 compiled DLL. Use '*' to force distutils' choice, suitable for 709 regular CPython C API modules. Use a file name ending in '.*' 710 to ask for the system's default extension for dynamic libraries 711 (.so/.dll/.dylib). 712 713 The default is '*' when building a non-embedded C API extension, 714 and (module_name + '.*') when building an embedded library. 715 """ 716 from .recompiler import recompile 717 # 718 if not hasattr(self, '_assigned_source'): 719 raise ValueError("set_source() must be called before compile()") 720 module_name, source, source_extension, kwds = self._assigned_source 721 return recompile(self, module_name, source, tmpdir=tmpdir, 722 target=target, source_extension=source_extension, 723 compiler_verbose=verbose, debug=debug, **kwds) 724 725 def init_once(self, func, tag): 726 # Read _init_once_cache[tag], which is either (False, lock) if 727 # we're calling the function now in some thread, or (True, result). 728 # Don't call setdefault() in most cases, to avoid allocating and 729 # immediately freeing a lock; but still use setdefaut() to avoid 730 # races. 731 try: 732 x = self._init_once_cache[tag] 733 except KeyError: 734 x = self._init_once_cache.setdefault(tag, (False, allocate_lock())) 735 # Common case: we got (True, result), so we return the result. 736 if x[0]: 737 return x[1] 738 # Else, it's a lock. Acquire it to serialize the following tests. 739 with x[1]: 740 # Read again from _init_once_cache the current status. 741 x = self._init_once_cache[tag] 742 if x[0]: 743 return x[1] 744 # Call the function and store the result back. 745 result = func() 746 self._init_once_cache[tag] = (True, result) 747 return result 748 749 def embedding_init_code(self, pysource): 750 if self._embedding: 751 raise ValueError("embedding_init_code() can only be called once") 752 # fix 'pysource' before it gets dumped into the C file: 753 # - remove empty lines at the beginning, so it starts at "line 1" 754 # - dedent, if all non-empty lines are indented 755 # - check for SyntaxErrors 756 import re 757 match = re.match(r'\s*\n', pysource) 758 if match: 759 pysource = pysource[match.end():] 760 lines = pysource.splitlines() or [''] 761 prefix = re.match(r'\s*', lines[0]).group() 762 for i in range(1, len(lines)): 763 line = lines[i] 764 if line.rstrip(): 765 while not line.startswith(prefix): 766 prefix = prefix[:-1] 767 i = len(prefix) 768 lines = [line[i:]+'\n' for line in lines] 769 pysource = ''.join(lines) 770 # 771 compile(pysource, "cffi_init", "exec") 772 # 773 self._embedding = pysource 774 775 def def_extern(self, *args, **kwds): 776 raise ValueError("ffi.def_extern() is only available on API-mode FFI " 777 "objects") 778 779 def list_types(self): 780 """Returns the user type names known to this FFI instance. 781 This returns a tuple containing three lists of names: 782 (typedef_names, names_of_structs, names_of_unions) 783 """ 784 typedefs = [] 785 structs = [] 786 unions = [] 787 for key in self._parser._declarations: 788 if key.startswith('typedef '): 789 typedefs.append(key[8:]) 790 elif key.startswith('struct '): 791 structs.append(key[7:]) 792 elif key.startswith('union '): 793 unions.append(key[6:]) 794 typedefs.sort() 795 structs.sort() 796 unions.sort() 797 return (typedefs, structs, unions) 798 799 800def _load_backend_lib(backend, name, flags): 801 import os 802 if name is None: 803 if sys.platform != "win32": 804 return backend.load_library(None, flags) 805 name = "c" # Windows: load_library(None) fails, but this works 806 # on Python 2 (backward compatibility hack only) 807 first_error = None 808 if '.' in name or '/' in name or os.sep in name: 809 try: 810 return backend.load_library(name, flags) 811 except OSError as e: 812 first_error = e 813 import ctypes.util 814 path = ctypes.util.find_library(name) 815 if path is None: 816 if name == "c" and sys.platform == "win32" and sys.version_info >= (3,): 817 raise OSError("dlopen(None) cannot work on Windows for Python 3 " 818 "(see http://bugs.python.org/issue23606)") 819 msg = ("ctypes.util.find_library() did not manage " 820 "to locate a library called %r" % (name,)) 821 if first_error is not None: 822 msg = "%s. Additionally, %s" % (first_error, msg) 823 raise OSError(msg) 824 return backend.load_library(path, flags) 825 826def _make_ffi_library(ffi, libname, flags): 827 backend = ffi._backend 828 backendlib = _load_backend_lib(backend, libname, flags) 829 # 830 def accessor_function(name): 831 key = 'function ' + name 832 tp, _ = ffi._parser._declarations[key] 833 BType = ffi._get_cached_btype(tp) 834 value = backendlib.load_function(BType, name) 835 library.__dict__[name] = value 836 # 837 def accessor_variable(name): 838 key = 'variable ' + name 839 tp, _ = ffi._parser._declarations[key] 840 BType = ffi._get_cached_btype(tp) 841 read_variable = backendlib.read_variable 842 write_variable = backendlib.write_variable 843 setattr(FFILibrary, name, property( 844 lambda self: read_variable(BType, name), 845 lambda self, value: write_variable(BType, name, value))) 846 # 847 def addressof_var(name): 848 try: 849 return addr_variables[name] 850 except KeyError: 851 with ffi._lock: 852 if name not in addr_variables: 853 key = 'variable ' + name 854 tp, _ = ffi._parser._declarations[key] 855 BType = ffi._get_cached_btype(tp) 856 if BType.kind != 'array': 857 BType = model.pointer_cache(ffi, BType) 858 p = backendlib.load_function(BType, name) 859 addr_variables[name] = p 860 return addr_variables[name] 861 # 862 def accessor_constant(name): 863 raise NotImplementedError("non-integer constant '%s' cannot be " 864 "accessed from a dlopen() library" % (name,)) 865 # 866 def accessor_int_constant(name): 867 library.__dict__[name] = ffi._parser._int_constants[name] 868 # 869 accessors = {} 870 accessors_version = [False] 871 addr_variables = {} 872 # 873 def update_accessors(): 874 if accessors_version[0] is ffi._cdef_version: 875 return 876 # 877 for key, (tp, _) in ffi._parser._declarations.items(): 878 if not isinstance(tp, model.EnumType): 879 tag, name = key.split(' ', 1) 880 if tag == 'function': 881 accessors[name] = accessor_function 882 elif tag == 'variable': 883 accessors[name] = accessor_variable 884 elif tag == 'constant': 885 accessors[name] = accessor_constant 886 else: 887 for i, enumname in enumerate(tp.enumerators): 888 def accessor_enum(name, tp=tp, i=i): 889 tp.check_not_partial() 890 library.__dict__[name] = tp.enumvalues[i] 891 accessors[enumname] = accessor_enum 892 for name in ffi._parser._int_constants: 893 accessors.setdefault(name, accessor_int_constant) 894 accessors_version[0] = ffi._cdef_version 895 # 896 def make_accessor(name): 897 with ffi._lock: 898 if name in library.__dict__ or name in FFILibrary.__dict__: 899 return # added by another thread while waiting for the lock 900 if name not in accessors: 901 update_accessors() 902 if name not in accessors: 903 raise AttributeError(name) 904 accessors[name](name) 905 # 906 class FFILibrary(object): 907 def __getattr__(self, name): 908 make_accessor(name) 909 return getattr(self, name) 910 def __setattr__(self, name, value): 911 try: 912 property = getattr(self.__class__, name) 913 except AttributeError: 914 make_accessor(name) 915 setattr(self, name, value) 916 else: 917 property.__set__(self, value) 918 def __dir__(self): 919 with ffi._lock: 920 update_accessors() 921 return accessors.keys() 922 def __addressof__(self, name): 923 if name in library.__dict__: 924 return library.__dict__[name] 925 if name in FFILibrary.__dict__: 926 return addressof_var(name) 927 make_accessor(name) 928 if name in library.__dict__: 929 return library.__dict__[name] 930 if name in FFILibrary.__dict__: 931 return addressof_var(name) 932 raise AttributeError("cffi library has no function or " 933 "global variable named '%s'" % (name,)) 934 def __cffi_close__(self): 935 backendlib.close_lib() 936 self.__dict__.clear() 937 # 938 if libname is not None: 939 try: 940 if not isinstance(libname, str): # unicode, on Python 2 941 libname = libname.encode('utf-8') 942 FFILibrary.__name__ = 'FFILibrary_%s' % libname 943 except UnicodeError: 944 pass 945 library = FFILibrary() 946 return library, library.__dict__ 947 948def _builtin_function_type(func): 949 # a hack to make at least ffi.typeof(builtin_function) work, 950 # if the builtin function was obtained by 'vengine_cpy'. 951 import sys 952 try: 953 module = sys.modules[func.__module__] 954 ffi = module._cffi_original_ffi 955 types_of_builtin_funcs = module._cffi_types_of_builtin_funcs 956 tp = types_of_builtin_funcs[func] 957 except (KeyError, AttributeError, TypeError): 958 return None 959 else: 960 with ffi._lock: 961 return ffi._get_cached_btype(tp) 962