C++中如何使用dlopen()解决tensorflow c-api与protobuf链接段错误问题
核心逻辑
dlopen方案不需要你修改cpp-wrapper的内部业务实现,核心是替换原本的编译期链接行为,改成运行期动态加载TensorFlow C API符号,只需要额外加一层适配层即可。
具体实现步骤
1. 移除编译期TensorFlow链接依赖
修改你的构建配置(Makefile/CMakeLists.txt等),删除原本的-ltensorflow链接选项,TensorFlow头文件可以正常保留引入,不需要修改cpp-wrapper的原有头文件结构。
2. 编写动态加载适配代码
单独新建一个源文件(例如tf_dynamic_loader.cc),实现TensorFlow库的加载和符号绑定逻辑,示例代码如下:
#include <dlfcn.h> #include "tensorflow/c/c_api.h" // 全局TensorFlow库句柄 static void* tf_lib_handle = nullptr; // 声明你用到的所有TF C API对应的函数指针,这里举几个常用的示例 decltype(&TF_NewStatus) tf_fp_NewStatus = nullptr; decltype(&TF_DeleteStatus) tf_fp_DeleteStatus = nullptr; decltype(&TF_NewGraph) tf_fp_NewGraph = nullptr; decltype(&TF_DeleteGraph) tf_fp_DeleteGraph = nullptr; // 其他用到的TF C API函数按相同格式补充声明 // 初始化函数,在所有TF相关逻辑执行前调用一次即可 bool load_tensorflow_runtime() { if (tf_lib_handle != nullptr) { return true; } // 加载libtensorflow.so,可写绝对路径避免加载到错误版本的库 tf_lib_handle = dlopen("libtensorflow.so", RTLD_NOW | RTLD_DEEPBIND); if (!tf_lib_handle) { // 可自行调用dlerror()打印具体错误信息 return false; } // 逐个绑定函数符号 tf_fp_NewStatus = (decltype(&TF_NewStatus))dlsym(tf_lib_handle, "TF_NewStatus"); tf_fp_DeleteStatus = (decltype(&TF_DeleteStatus))dlsym(tf_lib_handle, "TF_DeleteStatus"); tf_fp_NewGraph = (decltype(&TF_NewGraph))dlsym(tf_lib_handle, "TF_NewGraph"); tf_fp_DeleteGraph = (decltype(&TF_DeleteGraph))dlsym(tf_lib_handle, "TF_DeleteGraph"); // 其他函数按相同格式绑定 // 校验所有符号是否加载成功 if (!tf_fp_NewStatus || !tf_fp_DeleteStatus || !tf_fp_NewGraph || !tf_fp_DeleteGraph) { dlclose(tf_lib_handle); tf_lib_handle = nullptr; return false; } return true; } // 可选:程序退出前调用释放资源 void unload_tensorflow_runtime() { if (tf_lib_handle) { dlclose(tf_lib_handle); tf_lib_handle = nullptr; } }
3. 新增宏替换对接cpp-wrapper
不需要修改cpp-wrapper的任何业务代码,只需要在cpp-wrapper引入TensorFlow头文件的位置之后,新增批量宏定义,把原有调用的TF API替换成你加载的函数指针即可:
// 放在cpp-wrapper引入tensorflow/c/c_api.h的代码之后 #define TF_NewStatus tf_fp_NewStatus #define TF_DeleteStatus tf_fp_DeleteStatus #define TF_NewGraph tf_fp_NewGraph #define TF_DeleteGraph tf_fp_DeleteGraph // 其他用到的TF API按相同格式补充宏定义
4. 调整调用逻辑
在你的主程序第一次执行任何TensorFlow、cpp-wrapper相关代码之前,先调用load_tensorflow_runtime(),确认返回成功后再执行后续业务逻辑即可。
注意事项
- 编译你的开发包时,需要新增
-ldl链接选项,dlopen系列函数依赖libdl.so - 如果需要固定TF版本,可以在dlopen时指定带版本号的库名,例如
libtensorflow.so.2.15.0避免版本不兼容 - 如果程序退出时需要主动释放资源,可以在退出前调用
unload_tensorflow_runtime(),不调用也不会有泄漏,进程退出时系统会自动回收资源
内容的提问来源于stack exchange,提问作者Emilio7773
相关产品推荐
相关产品推荐

