我有一个C源/头文件,它是更大项目的一部分。我想将其作为一个单元进行测试,与实际项目无关。虽然可以通过创建一个具有不同main()
的新项目在C中执行此操作,但我想看看我是否可以使用Python(3)及其框架(例如,nose)来加速构建测试,使用现有的报告框架等。
我的印象是我可以用CFFI做到这一点。这是一个示例C文件:
// magic.c
// Implementation of magic.
int add(int a, int b)
{
return a;
}
标题:
// magic.h
// Add two numbers (where a + b is not greater than INT_MAX).
int add(int a, int b);
这是一个只是尝试编译它的脚本,所以我可以调用一些函数:
# cffi_test.py
import cffi
INCLUDE_DIRS = ('.',)
SOURCES = ('magic.c',)
ffi = cffi.FFI()
ffi.set_source(
'_magic_tests',
'#include "magic.h"',
include_dirs = INCLUDE_DIRS,
sources = SOURCES,
libraries = [],
)
ffi.compile()
最终,我计划在进行一系列单元测试之前将其作为设置的一部分。纯Python函数test_add()
将通过add()
对象调用并检查C函数ffi
的结果,该对象是在测试设置中构建的。
以上脚本似乎有效;它运行时没有错误,它会创建一个_magic_tests.c
文件,一个_magic_tests.cp35-win32.pyd
文件和一个Release
目录。我也可以import _magic_tests
没有错误。
但我无法弄清楚如何通过CFFI实际调用C函数。我找不到set_source()
函数的任何文档,它似乎是整个过程中不可或缺的一部分。 overview提到了很多,但reference包含零次。文档执行在calling functions上有一个部分,但它引用了一些lib
对象而没有显示它是如何创建的。如果我查看前面的示例,那么从lib
创建了一个ffi.dlopen()
对象,但我不知道如何将其应用于CFFI本身正在生成的内容。
我的大问题(即我的X problem)是:
我当前的方法(即我的Y problems)产生的问题是:
set_source()
的文档在哪里?我怎样才能找出需要的论据?lib
个对象?我目前的设置是:
我正在使用Christoph Gohlke's repository中的CFFI和pycparser。
答案 0 :(得分:12)
对于我的项目,我使用cffi
来测试我的C代码。 IMHO cffi
是一个很好的工具,可以为C代码生成python绑定,因此认为它是一个合理的工具,用于从python调用和测试C函数。但是,您的代码只会像C代码一样跨平台,因为您必须为每个平台编译绑定。
您可以在下面找到一些可以回答您问题的文档。另外,我写了一些示例代码来说明如何使用cffi
。有关更大的示例,您可以在https://github.com/ntruessel/qcgc/tree/master/test找到我的项目。
set_source()
的文档可在此处找到https://cffi.readthedocs.io/en/latest/cdef.html
https://cffi.readthedocs.io/en/latest/overview.html解释了如何使用CFFI,我建议使用API,不在线。
你的四个例子build_magic_tests.py
看起来像这样:
from cffi import FFI
ffibuilder = FFI()
# For every function that you want to have a python binding,
# specify its declaration here
ffibuilder.cdef("""
int add(int a, int b);
""")
# Here go the sources, most likely only includes and additional functions if necessary
ffibuilder.set_source("magic_tests",
"""
#include "magic.h"
""", sources=["magic.c"])
if __name__ == "__main__":
ffibuilder.compile()
要生成magic_tests模块,您必须运行python build_magic_tests.py
。生成的模块可以像这样导入和使用:
from magic_tests import ffi, lib
def run_add():
assert 4 == lib.add(4, 5)