在Python cffi中的库之间传递对象
如果我使用在Python cffi中的库之间传递对象,python,python-cffi,Python,Python Cffi,如果我使用cffi.FFI.new创建一个新结构,我如何将它从具有相同结构定义的不同FFI传递给函数 我有一个基本的C结构,我通过cffi包在Python中使用它,我想在运行时将它传递给cffi生成和编译的各种函数。但是,我不知道如何使生成的函数共享相同的结构定义,以便在它们之间传递对象。当使用一个FFI构建对象并将其从另一个FFI传递给函数时,cffi不喜欢它 下面是一个简化的可运行结构定义示例,并使用Python创建实例: from cffi import FFI common_heade
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_对象
,并将其传递给另一个FFI
中定义的函数,该函数有自己的my_结构
类型定义
如何编译生成的函数以与中心FFI共享结构定义?您可以使用
FFI.include
将一个FFI
实例的源代码和定义包含在另一个实例中。使用包含的FFI
构造的对象可以传递到包含它的FFI
中的函数
请注意,包含的定义不能在以后的FFI
中重复。此外,只有对set\u 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
# 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