![](/img/trans.png)
[英]How to implement a C interface in Python and pass objects using CFFI
[英]Pass objects between libraries in Python cffi
如果使用cffi.FFI.new
创建新结构,如何将其传递给具有相同结构定义的其他FFI
中的函数?
我有一个基本的C结构,正在通过cffi包在Python中使用,我想在运行时传递给cffi生成和编译的各种函数。 但是,我不知道如何获取生成的函数以共享相同的结构定义,以便我可以在它们之间传递对象。 当使用一个FFI
构建对象并将其从另一个FFI
传递给函数时,cffi不喜欢它。
这是结构定义和在Python中创建实例的简化可运行示例:
from cffi import FFI
common_header = """
typedef struct {
int32_t a;
double b;
} my_struct;
"""
# FFI for building objects
ffibuilder = FFI()
ffibuilder.cdef(common_header)
# Build an object in Python
my_object = ffibuilder.new('my_struct*')
my_object.a = 3
my_object.b = 2.0
我有一个外部库,该库生成函数的源代码,这些函数采用指向此结构实例的指针。 我目前使用CFFI的API模式进行编译。 这里重要的是,这些函数可以在构造对象之后生成,因此我不能简单地提前将所有函数收集在一起并将它们编译为一个库。
# Builder for functions generated at runtime
def build_library(header: str, source: str):
from tempfile import TemporaryDirectory
ffitemp = FFI()
ffitemp.cdef(common_header + header)
ffitemp.set_source('_temp', source)
with TemporaryDirectory() as temp_dir:
lib_path = ffitemp.compile(tmpdir=temp_dir)
lib = ffitemp.dlopen(lib_path)
return lib.func
# Use function
header = """
int func(my_struct *A);
"""
source = """
typedef struct {
int32_t a;
double b;
} my_struct;
int func(my_struct *A) {
return A -> a;
}
"""
func = build_library(header, source)
当我尝试将结构的实例传递给函数时,我收到一条错误消息,提示我传递的结构与函数接受的结构类型不同。
# Use function
a = func(my_object)
print(a)
TypeError: initializer for ctype 'my_struct *' appears indeed to be
'my_struct *', the types are different (check that you are not e.g.
mixing up different ffi instances)
该错误非常清楚为什么不满意。 它不喜欢我使用ffibuilder
构造my_object
并将其传递给另一个FFI
定义的函数,而FFI
具有自己的my_struct
类型定义。
如何获得所生成函数的编译结果以与中央FFI共享结构定义?
您可以使用FFI.include
将一个FFI
实例的源和定义包含在另一个FFI
实例中。 使用包含的FFI
构造的对象可传递到包含它的FFI
中的功能。
注意,包含的定义不能在以后的FFI
重复。 同样,只有在已调用set_source
下,才能包括FFI
。 即使您只需要标头,也是如此。 在这种情况下,只需将源设置为空字符串。
这是在主FFI
上设置空源:
from cffi import FFI
common_header = """
typedef struct {
int32_t a;
double b;
} my_struct;
"""
# FFI for building objects
ffibuilder = FFI()
ffibuilder.cdef(common_header)
ffibuilder.set_source('_main', '') # <-- Set empty source
这里是包括主FFI
在叶FFI
:
# Builder for functions generated at runtime
def build_library(header: str, source: str):
from tempfile import TemporaryDirectory
ffitemp = FFI()
ffitemp.include(ffibuilder) # <-- include main FFI
ffitemp.cdef(header)
ffitemp.set_source('_temp', source)
with TemporaryDirectory() as temp_dir:
lib_path = ffitemp.compile(tmpdir=temp_dir)
lib = ffitemp.dlopen(lib_path)
return lib.func
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.