当前位置: 首页 > 工具软件 > CFFI > 使用案例 >

Python使用CFFI调用C动态库

解沈义
2023-12-01

初始化

from cffi import FFI
ffi = FFI()

| 版权声明:itisyang,未经博主允许不得转载。https://blog.csdn.net/itisyang/article/details/54426631

加载C动态库

lib_IOTCAPIs = ffi.dlopen("./tutk_lib/libIOTCAPIs.so")

这种方法加载动态库若是多个库之间有交错调用,则会报错,若多个库之间存在交错调用,可使用下面的方法

lib_IOTCAPIs = ffi.dlopen("./tutk_lib/libIOTCAPIs.so", flags=256)  # RTLD_GLOBAL = 256

此处dlopen使用方法同标准C中void *dlopen(const char *filename, int flags);相似

加载并调用C动态库函数

ffi.cdef("int IOTC_Initialize2(unsigned short nUDPPort);")
lib_IOTCAPIs.IOTC_Initialize2(0)  # 调用

加载并调用C结构体

ffi.cdef("""
typedef struct{
    unsigned int channel;
    unsigned char reserved[];
}SMsgAVIoctrlAVStream;
""")
buf = ffi.new('SMsgAVIoctrlAVStream *', [ChannelID, 4]) 
buf1 = ffi.new('SMsgAVIoctrlAVStream ', [ChannelID, “1234”])  # 调用
buf2 = ffi.new('SMsgAVIoctrlAVStream[]', 10)
buf3 = ffi.new('SMsgAVIoctrlAVStream[10]')

分别调用了结构体指针、结构体、结构体数组,buf2和buf3效果是相同的

加载并调用C基本类型

基本类型包括 int、 char、unsigned int、unsigned char、 char[]、int[]、int*、char **…

x = ffi.new("char[]", "hello")
print len(x),x[0],ffi.string(x)

输出 6 h hello

array = ffi.new("int[]", [1, 2, 3, 4])

相当于int array[] = { 1, 2, 3, 4 };

x = ffi.new("int *")
x[0] = 42
print x[0]

输出 42

调用标准C函数

ffi.cdef("""
int printf(const char *format, ...);   // copy-pasted from the man page
""")
C = ffi.dlopen(None)                     # 导入全部C函数命名空间
arg = ffi.new("char[]", "world")         # 相当于 char arg[] = "world";
C.printf("hi there, %s.\n", arg)         # 调用 printf

输出 hi there, world.

转换指针类型

frame_info = ffi.new('PPSDEV_MEDIA_HEADER *')
frame_p = ffi.cast("char *", frame)

将 PPSDEV_MEDIA_HEADER* 指针转换为 char* 指针

加载C头文件

ffi.cdef("""
#include <library.h>
""")

若需要使用的库函数过多,一个一个加载麻烦,可采用这种方法一次性加载
注意头文件中的函数接口需要写成标准的方式,一些为跨平台写的东西有可能报错,跨平台性能最好是在动态库中包含,在头文件剔除

 类似资料: