Python3 cffi如何合并两个独立FFI实例以实现跨实例类型互传
报错原因
这个报错是CFFI的独立类型系统设计导致的:每个FFI实例都会维护自己独有的类型树,哪怕两个不同FFI实例中定义的Foo结构完全和底层C实现一致,在Python层面也会被识别为完全不同的类型,不允许直接跨实例传递。
可行方案
不需要合并两个FFI实例,也不需要把两个库的接口整合到一起,以下两种方案可以直接实现类型跨实例互通:
指针类型互通(零开销,推荐)
不需要拷贝数据,只需要把指针转成整数地址中转即可:
# 从第一个FFI实例的指针中提取内存地址 foo_address = int(first_ffi.cast("uintptr_t", first_ffi_foo)) # 用第二个FFI实例将地址包装为对应类型的指针 second_ffi_foo = second_ffi.cast("Foo *", foo_address)
只要你确认两个FFI中Foo的定义和底层C实现完全匹配,这个方法没有额外性能开销,只是对同一块内存地址做了不同的类型包装。
结构体值互通(适用于非指针传递场景)
如果需要传递的是结构体本身而非指针,通过字节串中转内存内容即可:
# 读取第一个FFI实例中结构体的原始内存字节 foo_raw_bytes = bytes(first_ffi.buffer(first_ffi_foo)) # 在第二个FFI实例中创建结构体对象并写入内存内容 second_ffi_foo = second_ffi.new("Foo *") second_ffi.memmove(second_ffi_foo, foo_raw_bytes, len(foo_raw_bytes))
注意事项
- 以上所有方案生效的前提是两个FFI实例中对应C类型的内存布局和底层实际实现完全一致
- 使用指针中转方案时需要确保原对象在第二个FFI使用完毕前不会被释放或被GC回收,避免出现野指针问题
- 如果有大量公共类型需要互通,可以把公共类型定义抽成单独的头文件片段,两个FFI实例初始化时都加载这部分定义,避免后续类型不匹配的问题
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

