CMAKE相对路径编译和python的ctypes引用
CMAKE相对路径编译和python的ctypes引用
cmake 编译库使用相对路径
cmake 编译使用相对路径生成动态库,进而满足其他代码的调用,如python的ctypes
由于ctypes能调用c,而不能调用c++,所以,使用extern c来处理,使ctypes能够调用。
- extern c
在需要编译动态库cpp代码中,使用C的方式处理函数名yyy
extern c yyy
例如
extern "C" int main(int argc, char *argv[])
- 修改cmakelists,使用相对路径编译。
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH $ORIGIN)
- 正常使用cmake 编译
cmake ..
4.检查extern C 是否生效
查看xxx.so动态库是否有yyy的函数
objdump -T xxx.so | grep yyy
如果查询到有yyy,表示可以使用ctypes调用。
python的ctypes调用so
# 导入ctypes
from ctypes import *
# 获取当前运行文件的路径
lib_dir=os.path.dirname(os.path.abspath(__file__))
# 设置so路径
path=os.path.join(lib_dir,'xxx/xxx.so')
# 加载动态库 so 文件
library = cdll.LoadLibrary(path)
# 构造参数
param=(c_char_p * 3)(b'./main',b'arg1',b'arg2')
# 注意 c_char_p 为后面传参的参数数量,如
# param=(c_char_p * 3)(b'./main',b'-o',b'123')
# 等效于在命令行 ./main -o 123
# 设置返回类型和传参类型
library.main.restype = c_int
library.main.argtype = c_int,POINTER(c_char_p)
ret = library.main(len(param),param)
# 如果如果library.main函数有多个数据返回,可以定义以结构体的数据进行返回。
class test_struct(Structure):
_fields_ = [('a',c_int32),
('b',c_int32),
('c',c_int32),
('d',c_int32),
]
# 调用library.main执行
ret = library.main(len(param),param)
# 获取返回值,由于c的main函数一般是int类型,所以在cpp里开发了get_info,用来获取数据
# 调用动态库中的 so 文件中的 get_info 函数
library.get_info.restype = POINTER(test_struct) # 设置返回值
restruct = library.get_info() # 调用并返回结构体,注意get_info 函数没有任何需要传的参数,所以未定义 argtype
# 将调用的值放到python中
a = restruct.contents.a
b = restruct.contents.b
c = restruct.contents.c