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