在 Python cffi 中的库之间传递对象
Pass objects between libraries in Python cffi
如果我使用 cffi.FFI.new
创建一个新结构,如何将其传递给具有相同结构定义的不同 FFI
的函数?
我有一个基本的 C 结构,我在 Python 中通过 cffi 包使用它,我想将其传递给 cffi 在运行时生成和编译的各种函数。但是,我不知道如何让生成的函数共享相同的结构定义,以便我可以在它们之间传递对象。 cffi 不喜欢用一个 FFI
构建对象并将其传递给另一个 FFI
.
的函数
这是结构定义和在 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
中定义的函数,它有自己的 my_struct
类型定义。
如何编译生成的函数以与中央 FFI 共享结构定义?
您可以使用 FFI.include
将一个 FFI
实例的来源和定义包含在另一个实例中。使用包含的 FFI
构造的 Objects 可传递给包含它的 FFI
中的函数。
请注意,包含的定义不能在以后的 FFI
中重复。此外,只有在调用 set_source
时才能包含 FFI
。即使您想要的只是 header,也是如此;在这种情况下,只需将源设置为空字符串即可。
这里是在main上设置空源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
如果我使用 cffi.FFI.new
创建一个新结构,如何将其传递给具有相同结构定义的不同 FFI
的函数?
我有一个基本的 C 结构,我在 Python 中通过 cffi 包使用它,我想将其传递给 cffi 在运行时生成和编译的各种函数。但是,我不知道如何让生成的函数共享相同的结构定义,以便我可以在它们之间传递对象。 cffi 不喜欢用一个 FFI
构建对象并将其传递给另一个 FFI
.
这是结构定义和在 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
中定义的函数,它有自己的 my_struct
类型定义。
如何编译生成的函数以与中央 FFI 共享结构定义?
您可以使用 FFI.include
将一个 FFI
实例的来源和定义包含在另一个实例中。使用包含的 FFI
构造的 Objects 可传递给包含它的 FFI
中的函数。
请注意,包含的定义不能在以后的 FFI
中重复。此外,只有在调用 set_source
时才能包含 FFI
。即使您想要的只是 header,也是如此;在这种情况下,只需将源设置为空字符串即可。
这里是在main上设置空源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