如何使用 Python CFFI 正确包装 C 库

Posted

技术标签:

【中文标题】如何使用 Python CFFI 正确包装 C 库【英文标题】:How to properly wrap a C library with Python CFFI 【发布时间】:2016-12-23 03:02:18 【问题描述】:

我正在尝试包装一个非常简单的 C 库,其中只包含两个 .C 源文件:dbc2dbf.cblast.c

我正在执行以下操作(来自文档):

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)

这不是很有效。我认为我没有正确包含 blast.c

谁能帮忙?

【问题讨论】:

不确定为什么需要两个FFI() 实例。这当然不在文档中... 【参考方案1】:

这是解决方案(已测试):

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)

【讨论】:

我认为我仍然可以摆脱 'blast.h' 上的 cdef,因为我不需要从那里公开任何函数。 我应该提到,如果没有@armin-rigo 的帮助,我将找不到这个解决方案!再次感谢!

以上是关于如何使用 Python CFFI 正确包装 C 库的主要内容,如果未能解决你的问题,请参考以下文章

使用 CFFI 从 Python 传递指向 C 函数的指针的最佳方法

为自定义 C 库分发 CFFI 包装器

Python cffi学习

使用 CFFI 在 Python 中创建 CData 类型的缓冲区

如何在 Numba 中使用指针包装 CFFI 函数

我可以用 C 包装 OpenCV 的 C++ 接口,然后用 Lisp 的 CFFI 包装它吗?