CMAKE相对路径编译和python的ctypes引用

发布时间 2023-09-14 15:16:59作者: 雪夜羽

CMAKE相对路径编译和python的ctypes引用

cmake 编译库使用相对路径

cmake 编译使用相对路径生成动态库,进而满足其他代码的调用,如python的ctypes

由于ctypes能调用c,而不能调用c++,所以,使用extern c来处理,使ctypes能够调用。

  1. extern c
    在需要编译动态库cpp代码中,使用C的方式处理函数名yyy
extern c yyy

例如

extern "C" int main(int argc, char *argv[])
  1. 修改cmakelists,使用相对路径编译。

set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH $ORIGIN)

  1. 正常使用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