问题描述

开发云台,拿到商家的SDK,抓取数据调用系统OpenCV库时一直报错,使用nm命令查看该动态库的符号导出,发现里面自己编译了一个2.4的OpenCV版本,链接后调用OpenCV函数会默认到该SDK里面查找符号然后调用,由于开发使用的是系统的3.3版本,程序一直崩溃

尝试解决

  • 将调用云台的代码生成动态库,调用OpenCV的放在可执行文件里,静态链接后运行问题依然存在
  • 将调用云台的代码生成动态库,调用OpenCV的放在可执行文件里,使用load_library依然存在问题

最终解决方案

查找资料发现可以使用-fvisibility=hidden参数仅仅导出需要的函数符号,通过在代码中加入__attribute__((visibility ("default"))),但是SDK没有源码

最后在load_library的函数文档中找到解决办法,通过添加RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND参数实现了,具体参数的解释如下:

RTLD_LAZY

执行惰性绑定。 仅在执行引用它们的代码时解析符号。 如果符号从未被引用,则它永远不会被解析。 (惰性绑定只对函数引用执行;对变量的引用总是在加载库时立即绑定。)

RTLD_GLOBAL

此库定义的符号将可用于随后加载的库的符号解析。

RTLD_LOCAL

这是 RTLD_GLOBAL 的反面,如果未指定任何标志,则为默认值。 此库中定义的符号不可用于解析后续加载的库中的引用。

RTLD_DEEPBIND

将此库中符号的查找范围放在全局范围之前。 这意味着自包含库将优先使用其自己的符号,而不是已加载的库中包含的同名全局符号。 POSIX.1-2001 中未指定此标志。