Windows环境下将.cpp及.lib编译为可被Python调用的.so共享库方法咨询
编译C++代码为.so共享库供Python调用的操作步骤
前置确认
你当前CLion项目可正常运行,说明依赖的头文件、库文件的逻辑是正确的,仅需注意:如果原依赖的.lib是Windows平台的静态库,需要先替换为对应Linux/macOS平台编译的库文件(.a静态库或.so动态库),跨平台的库文件无法直接链接。
步骤1:修改C++代码添加C接口声明
C++的函数名会在编译时被修饰,Python无法直接识别,需要给所有要暴露给Python调用的函数加上extern "C"声明,示例如下:
#ifdef __cplusplus extern "C" { #endif // 仅把需要被Python调用的函数声明放在这个代码块内 int your_custom_function(int param1, const char* param2); #ifdef __cplusplus } #endif // 原有函数实现完全保留,包括调用第三方库的逻辑不需要改动 int your_custom_function(int param1, const char* param2) { // 原有业务逻辑 }
注意不要直接暴露第三方依赖库的函数,仅暴露你自己实现的、需要被Python调用的顶层接口即可
步骤2:编译生成.so文件
你可以选择直接用命令行编译,或者修改CLion的CMake配置编译:
方式一:命令行编译
执行以下g++命令即可:
g++ -fPIC -shared your_cpp_file.cpp -o output_lib.so -I./path/to/header_dir -L./path/to/lib_dir -lyour_dep_lib_name
参数说明:
-fPIC:生成位置无关代码,是编译共享库的必填参数-shared:指定输出产物为共享库-I(大写i):后面跟依赖的头文件所在文件夹路径,有多个头文件目录就加多个-I参数-L:后面跟依赖的库文件所在文件夹路径,有多个库目录就加多个-L参数-l(小写L):后面跟依赖库的名称,比如依赖的库文件是libtest.a,这里就写-ltest,去掉前缀lib和后缀即可
方式二:修改CLion的CMakeLists.txt编译
只需要把原来生成可执行文件的配置改成生成共享库即可,其余依赖配置和你当前可正常运行的配置完全一致,示例:
cmake_minimum_required(VERSION 3.16) project(your_project_name) set(CMAKE_CXX_STANDARD 17) # 把原来的add_executable替换为add_library,添加SHARED参数 add_library(output_lib SHARED your_cpp_file.cpp) # 以下的头文件、链接库配置和你原有正常运行的配置完全相同即可 include_directories(./path/to/header_dir) link_directories(./path/to/lib_dir) target_link_libraries(output_lib your_dep_lib_name)
修改后直接在CLion执行构建,即可在构建输出目录找到生成的.so文件。
步骤3:Python端调用验证
使用Python内置的ctypes库调用即可,示例:
from ctypes import cdll, c_int, c_char_p # 加载so库 lib = cdll.LoadLibrary("./output_lib.so") # 声明函数的参数类型、返回值类型,要和C接口的定义完全对应 lib.your_custom_function.argtypes = [c_int, c_char_p] lib.your_custom_function.restype = c_int # 调用函数 res = lib.your_custom_function(10, b"test_param") print(res)
常见问题排查
- 如果出现找不到依赖库的报错,Linux下执行
export LD_LIBRARY_PATH=./path/to/your/dep_lib_dir:$LD_LIBRARY_PATH后再运行Python脚本即可 - 如果函数返回值/参数异常,优先检查ctypes声明的参数、返回值类型是否和C接口完全匹配
内容的提问来源于stack exchange,提问作者Tareyes
相关产品推荐
相关产品推荐

