cffi: C Foreign Function Interface
Use cffi for more Pythonic C interop with inline C declarations.
cffi: C Foreign Function Interface is a free Python Academy lesson on CoddyKit. This is lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, and your progress syncs across the web and the CoddyKit app. The Python Academy course includes 4 lessons in total.
What Is cffi?
cffi (C Foreign Function Interface) lets you call C code from Python using C declarations rather than ctypes classes. It is more Pythonic and often safer.
# pip install cffi
from cffi import FFI
ffi = FFI()
ffi.cdef("double sqrt(double x);")
libm = ffi.dlopen(None) # current process
print(libm.sqrt(2.0)) # 1.4142...ABI vs API Mode
ffi.dlopen() is ABI mode — calls an existing shared library at runtime. API mode compiles a C wrapper and is faster and more robust.
from cffi import FFI
ffi = FFI()
# ABI mode (no compile step):
ffi.cdef("int abs(int x);")
libc = ffi.dlopen("libc.so.6") # Linux
print(libc.abs(-42)) # 42cdef Declarations
Use ffi.cdef() to declare C function signatures, structs, and typedefs that you want to use from Python.
from cffi import FFI
ffi = FFI()
ffi.cdef("""
typedef struct {
double x;
double y;
} Point;
double distance(Point a, Point b);
""")
# lib = ffi.dlopen("mylib.so")Creating C Structs
Use ffi.new() to allocate a C struct and set its fields from Python.
from cffi import FFI
ffi = FFI()
ffi.cdef("typedef struct { int x; int y; } Vec2;")
lib = ffi.dlopen(None)
v = ffi.new("Vec2 *")
v.x = 3
v.y = 4
print(v.x, v.y) # 3 4Strings and Buffers
Use ffi.new("char[]", n) for mutable buffers and ffi.string(ptr) to convert a C string pointer to Python bytes.
from cffi import FFI
ffi = FFI()
buf = ffi.new("char[]", b"hello world")
print(ffi.string(buf)) # b"hello world"
# Mutable buffer for output:
out = ffi.new("char[128]")
# c_func(out, 128) # fill the buffer
# result = ffi.string(out).decode()API Mode with verify
API mode compiles a small C wrapper module for better type safety and performance. Use ffi.set_source() and build offline.
from cffi import FFI
ffi = FFI()
ffi.cdef("int add(int a, int b);")
ffi.set_source("_mylib",
"""
int add(int a, int b) { return a + b; }
"""
)
# Build: python build_mylib.py
# from _mylib import ffi, lib
# print(lib.add(3, 4)) # 7Callbacks from C to Python
Use ffi.callback() to wrap a Python function as a C function pointer that can be passed to a C library.
from cffi import FFI
ffi = FFI()
ffi.cdef("typedef int (*compare_fn)(int, int);")
@ffi.callback("int(int, int)")
def compare(a, b):
return a - b
# pass compare to a C sort functionMemory Management
Objects allocated with ffi.new() are owned by Python and freed automatically. Use ffi.gc(ptr, destructor) to attach a custom destructor.
from cffi import FFI
ffi = FFI()
# ptr freed when Python GC collects it:
buf = ffi.new("int[10]")
buf[0] = 42
print(buf[0]) # 42
# Custom destructor:
# ptr = ffi.gc(lib.alloc(), lib.free)cffi vs ctypes
cffi uses C declaration strings (more natural for C developers) while ctypes uses Python classes. cffi's API mode is faster; ctypes requires no compilation.
# ctypes approach:
import ctypes
libc = ctypes.CDLL("libc.so.6")
libc.abs.restype = ctypes.c_int
libc.abs.argtypes = [ctypes.c_int]
print(libc.abs(-5)) # 5
# cffi approach:
from cffi import FFI; ffi = FFI()
ffi.cdef("int abs(int);")
lib = ffi.dlopen(None)
print(lib.abs(-5)) # 5Using cffi with NumPy
Pass NumPy array data directly to C via cffi using ffi.cast() and the array's ctypes.data pointer.
import numpy as np
from cffi import FFI
ffi = FFI()
arr = np.array([1.0, 2.0, 3.0])
ptr = ffi.cast("double *", arr.ctypes.data)
# Now ptr can be passed to a C function expecting double*Error Handling with cffi
C functions typically signal errors via return values. Check return values and use ffi.errno for POSIX error codes.
import errno as errno_mod
from cffi import FFI
ffi = FFI()
ffi.cdef("int open(const char *path, int flags);")
lib = ffi.dlopen(None)
fd = lib.open(b"/nonexistent", 0)
if fd == -1:
err = ffi.errno
raise OSError(err, "open failed")Quick Check
What method does cffi use to declare the C function signatures you want to call?
Recap
cffi uses ffi.cdef() to declare C signatures and ffi.dlopen() for ABI-mode library calls. API mode compiles a wrapper for better performance. Use ffi.new() for C memory and ffi.callback() for Python-to-C callbacks.
Learn Python with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 76
- Lessons
- 320
Frequently Asked Questions
Is the “cffi: C Foreign Function Interface” lesson free?
Yes — the full text of “cffi: C Foreign Function Interface” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO. The Python Academy course includes 4 lessons in total.
What will I learn in “cffi: C Foreign Function Interface”?
Use cffi for more Pythonic C interop with inline C declarations. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Python Academy?
No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.
How long does the “cffi: C Foreign Function Interface” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Python Academy lesson?
Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Why C Extensions? Use Cases and Trade-offs
- ctypes: Calling C Libraries from Python
- cffi: C Foreign Function Interface
- Writing a Python C Extension Module