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
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
1import sys, types
2from .lock import allocate_lock
3from .error import CDefError
4from . import model
6try:
7 callable
8except NameError:
9 # Python 3.1
10 from collections import Callable
11 callable = lambda x: isinstance(x, Callable)
13try:
14 basestring
15except NameError:
16 # Python 3.x
17 basestring = str
19_unspecified = object()
23class FFI(object):
24 r'''
25 The main top-level class that you instantiate once, or once per module.
27 Example usage:
29 ffi = FFI()
30 ffi.cdef("""
31 int printf(const char *, ...);
32 """)
34 C = ffi.dlopen(None) # standard library
35 -or-
36 C = ffi.verify() # use a C compiler: verify the decl above is right
38 C.printf("hello, %s!\n", ffi.new("char[]", "world"))
39 '''
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.)
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
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)
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 = ''
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)
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
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)
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
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
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))
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)
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)
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]
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.
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.
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)
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.
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.
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
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)
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.
309 If 'cdata' is a pointer or array of wchar_t, returns a unicode
310 string following the same rules.
312 If 'cdata' is a single character or byte or a wchar_t, returns
313 it as a string or unicode string.
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)
320 def unpack(self, cdata, length):
321 """Unpack an array of C data of the given length,
322 returning a Python string/unicode/list.
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)[:]
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.
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)
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__
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.
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)
368 def memmove(self, dest, src, n):
369 """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest.
371 Like the C function memmove(), the memory areas may overlap;
372 apart from that it behaves like the C function memcpy().
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.
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)
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
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)
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.
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)
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
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
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")
482 def getwinerror(self, code=-1):
483 return self._backend.getwinerror(code)
485 def _pointer_to(self, ctype):
486 with self._lock:
487 return model.pointer_cache(self, ctype)
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)
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
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)
540 def new_handle(self, x):
541 return self._backend.newp_handle(self.BVoidP, x)
543 def from_handle(self, x):
544 return self._backend.from_handle(x)
546 def release(self, x):
547 self._backend.release(x)
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
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
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')
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)
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)
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
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)
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)
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).
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)
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
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
779 def def_extern(self, *args, **kwds):
780 raise ValueError("ffi.def_extern() is only available on API-mode FFI "
781 "objects")
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)
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)
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__
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)