• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
966