Search code examples
pythonpython-cffi

Compiling multiple source files with cffi


I have recently discovered the cffi Python module and I would like to use it to write unit tests for some C code I have written in Python. One (arguably simple) thing that I can't wrap my head around is how to compile several C source files into one Python module that can then be imported by Python code.

Say for example I have four C files, a.c, a.h, b.c and b.h such that a.c includes both a.h and b.h and calls functions implemented in b.c. And b.c only includes b.h.

If I wanted to write unit tests for functions implemented in b.c I could simply do this:

import cffi

with open('b.h', 'r') as f:
    b_h = f.read()

with open('b.c', 'r') as f:
    b_c = f.read()

ffi = cffi.FFI()

ffi.cdef(b_h)
ffi.set_source('_b', b_c)

# import _b ...

But what if I want to write unit tests for functions defined in a.c?


Solution

  • The core idea is to use:

    ffi.set_source("_mytest", '''
        #include "a.h"
    ''', sources=["a.c", "b.c"])
    

    to compile a module containing both a.c and b.c and including a.h, which itself includes b.h. This uses the distutils argument sources=[..] to give additional source files to be compiled into the same extension module. Above that line, you can use ffi.cdef() on the C declarations that are of interest to you---usually a subset of both a.h and b.h. (You can call ffi.cdef() more than once, or just once on a string made by concatenating several pieces.)