如何使用 python-cffi 包装 C 函数以便 python 关键字参数起作用?

问题描述

python-cffi 框架中使用 API mode,calling C sources instead of a compiled library 我想用关键字参数在 python 中调用我的 c 函数。 cffi 中是否有内置功能?否则我将不得不围绕我的 cffi 包装的 c 函数编写一个 python 包装器,我不想这样做,因为它看起来像一个丑陋的解决方案。

使用 python 运行这两个文件,如果存在 cffi 和 gcc,应该可以开箱即用:“python example_extension_build.py && python test_example.py”

注意:在此示例代码中,我使用了 API level,out-of-line 模式(用于 clearnes

# file: example_extension_build.py
from cffi import FFI
ffibuilder = FFI()

# objects shared between c and python
ffibuilder.cdef("""
    struct my_s{ int a; char * b; };
    int my_f(int,struct my_s);
""")

# deFinitions of the python-c shared objects
ffibuilder.set_source("_example",r"""

    struct my_s{ int a; char * b; };

    #include <stdio.h>
    int my_f(int arg_1,struct my_s arg_2) // some random example function
    {
        printf("%s\n",arg_2.b); 
        return arg_1 + arg_2.a;
    }

""",sources=[])

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

和 python 调用

# file: test_example.py
import _example as e

n = 21;

s = e.ffi.new("struct my_s *")
s.a = 21
s.b = e.ffi.new("char[]",b"Hello World!")

# e.lib.my_f(arg_2=s[0],arg_1=n); # <-- Here is what I want
e.lib.my_f(n,s[0]); # the standard way

解决方法

截至今天 - 2021 年 5 月 18 日 - 无法使用 cffi 包装 c 函数以将关键字参数暴露给 python。此答案由 Armin Rigo 在 cffi 邮件列表 here 上提供(如果满足某些条件,Armin Rigo 将接受提供此功能的补丁)。唯一可能的解决方案是将 cffi 包装的 c 函数包装在 python 代码中(呃)。

注意:如果想为 arg_2 设置默认参数值,它会变得更丑

# file: test_wrap.py
import _example as e

def my_f(arg_1,arg_2) :
    return e.lib.my_f(arg_1,arg_2)

n = 21

s = e.ffi.new("struct my_s *")
s.a = 21
s.b = e.ffi.new("char[]",b"Hello World!")

sol = my_f(arg_2=s[0],arg_1=n) # <-- Here is what I want

print(sol)

在命令行上

$ python test_wrap.py
Hello World!
42