Search code examples
pythoncpython-cffi

How to properly wrap a C library with Python CFFI


I am trying to wrap a very simple C library containing only two .C source files: dbc2dbf.c and blast.c

I am doing the following (from the documentation):

import os
from cffi import FFI
blastbuilder = FFI()
ffibuilder = FFI()
with open(os.path.join(os.path.dirname(__file__), "c-src/blast.c")) as f:
    blastbuilder.set_source("blast", f.read(), libraries=["c"])
with open(os.path.join(os.path.dirname(__file__), "c-src/blast.h")) as f:
    blastbuilder.cdef(f.read())
blastbuilder.compile(verbose=True)

with open('c-src/dbc2dbf.c','r') as f:
    ffibuilder.set_source("_readdbc",
                          f.read(),
                          libraries=["c"])

with open(os.path.join(os.path.dirname(__file__), "c-src/blast.h")) as f:
    ffibuilder.cdef(f.read(), override=True)

if __name__ == "__main__":
    # ffibuilder.include(blastbuilder)
    ffibuilder.compile(verbose=True)

This is not quite working. I think I am not including blast.c correctly;

can anyone help?


Solution

  • Here is the solution (tested):

    import os
    from cffi import FFI
    
    ffibuilder = FFI()
    
    PATH = os.path.dirname(__file__)
    
    with open(os.path.join(PATH, 'c-src/dbc2dbf.c'),'r') as f:
        ffibuilder.set_source("_readdbc",
                              f.read(),
                              libraries=["c"],
                              sources=[os.path.join(PATH, "c-src/blast.c")],
                              include_dirs=[os.path.join(PATH, "c-src/")]
                              )
    ffibuilder.cdef(
        """
        static unsigned inf(void *how, unsigned char **buf);
        static int outf(void *how, unsigned char *buf, unsigned len);
        void dbc2dbf(char** input_file, char** output_file);
        """
    )
    
    with open(os.path.join(PATH, "c-src/blast.h")) as f:
        ffibuilder.cdef(f.read(), override=True)
    
    if __name__ == "__main__":
        ffibuilder.compile(verbose=True)