cffi /

Full commit


Foreign Function Interface for Python calling C code. The aim of this project is to provide a convenient and reliable way of calling C code from Python. The interface is based on luajit FFI and follows a few principles:

  • The goal is to call C code from Python. You should be able to do so without learning a 3rd language: every alternative requires you to learn their own language (Cython, SWIG) or API (ctypes). So we tried to assume that you know Python and C and minimize the extra bits of API that you need to learn.

  • Keep all the Python-related logic in Python so that you don't need to write much C code (unlike CPython native C extensions).

  • Work either at the level of the ABI (Application Binary Interface) or the API (Application Programming Interface). Usually, C libraries have a specified C API but often not an ABI (e.g. they may document a "struct" as having at least these fields, but maybe more). (ctypes works at the ABI level, whereas native C extensions work at the API level.)

  • We try to be complete. For now some C99 constructs are not supported, but all C89 should be, including macros (apart from the most advanced (ab)uses of these macros).

Simple example (ABI level)

>>> from cffi import FFI
>>> ffi = FFI()
>>> ffi.cdef("""
...     int printf(const char *format, ...);     // copy-pasted from the man page
... """)                                  
>>> C = ffi.dlopen(None)                     # loads the entire C namespace
>>> arg ="char[]", "world")         # equivalent to C code: char arg[] = "world";
>>> C.printf("hi there, %s!\n", arg);        # call printf
hi there, world!

Simple example (API level)

from cffi import FFI
ffi = FFI()
ffi.cdef("""     // some declarations from the man page
    struct passwd {
        char *pw_name;
    struct passwd *getpwuid(int uid);
C = ffi.verify("""   // passed to the real C compiler
#include <sys/types.h>
#include <pwd.h>
assert str(C.getpwuid(0).pw_name) == 'root'

Note that the above example works independently of the exact layout of "struct passwd", but so far require a C compiler at runtime. (This will be improved with caching and distribution of the compiled code.)

More documentation

See More docs for examples and supported features.


Mailing list

Initial motivation