gcc 链接共享库有效,但同一共享库的 dlopen 失败
gcc linking shared library works, but dlopen of the same shared lib fails
我有一个看起来像这样的项目:
executable
\---> bsp.so
|---> bsp_protobuf.a
\---> protobuf.a
其中有两个首先构建的静态库(两个 protobuf 库)被静态 linked 到 bsp.so 共享库中。最后 bsp.so 被 link 编辑成可执行文件。
当我 link 可执行文件和 link bsp.so 在命令行上使用 gcc
时 link 没问题。
但是,如果我 dont link bsp.so 那么它也可以正常构建 - 这是设计使然 - 因为我想使用 dlopen()
确定我是否需要这个库(我有指向对象的指针,但是 none 实例化等...)。
我遇到的问题是,当我使用 dlopen()
(在代码中)时,由于未定义的符号,它无法打开库。有问题的符号位于静态库中。
我真正难以理解的是为什么它在命令行上有效,但在我使用 dlopen()
和运行时时却不起作用。
我还有 3-4 个可以成功使用 dlopen()
的其他共享库 - 所以我知道我使用 dlopen()
的一般过程很好。
我正在使用 dlerror()
来获取未定义符号错误消息。
我看过以下link:
how-to-force-symbols-from-a-static-library-to-be-included-in-a-shared-library-bu
how-to-apply-fvisibility-option-to-symbols-in-static-libraries
我把 -Wl,--whole-archive
的想法联系起来了,但这似乎牵扯太多,并且构建失败并出现了太多警告 - 可能与 google protobuf 东西有关,而且我不确定这是我最终想要采用的方法。
我检查了我的共享库是用 -fPIC
构建的,我不确定静态库是用 -fPIC
构建的还是需要?
我也看过这里:
讨论了如何 link 与 dlopen()
但这是使用 libtools - 我们没有为我们的所有目标提供它,所以我不想使用 libtools。
我真的不确定要采用哪种方法 - 感觉这应该是某个地方的简单修复 - 但正如我所说,我无法理解为什么一种方法有效而另一种方法无效.. .
更新
所以,在 Sam 的评论之后,我开始寻找正确的地方。事实证明,bsp.so 的 makefile 静态 link 只是两个库之一。
该共享库有一个单独的测试器,link 有两个库(因此测试器可以工作),我没有理由怀疑库已损坏......好吧,我学到了很多关于 dlopen 和 linking 等...:o
当您 link 具有共享库的可执行文件时,来自可执行文件的未解析符号引用必须由共享库解析,否则 link 失败。
当您 link 一个共享库时,不需要共享库本身的所有未解析符号都必须由它 link 与之相关的任何其他共享库解析;因此,当您 link 将共享库放在一起时,可能会从共享库本身中得到未解析的符号。
将可执行文件与共享库链接成功,因为可执行文件中所有未解析的符号都由共享库解析;但由于来自共享库本身的未解析符号引用,可执行文件将无法加载。或者,dlopen
()ing 共享库会产生相同的错误。
dlopen
手册页还介绍了几个可用于控制此行为的可选标志。
我有一个看起来像这样的项目:
executable
\---> bsp.so
|---> bsp_protobuf.a
\---> protobuf.a
其中有两个首先构建的静态库(两个 protobuf 库)被静态 linked 到 bsp.so 共享库中。最后 bsp.so 被 link 编辑成可执行文件。
当我 link 可执行文件和 link bsp.so 在命令行上使用 gcc
时 link 没问题。
但是,如果我 dont link bsp.so 那么它也可以正常构建 - 这是设计使然 - 因为我想使用 dlopen()
确定我是否需要这个库(我有指向对象的指针,但是 none 实例化等...)。
我遇到的问题是,当我使用 dlopen()
(在代码中)时,由于未定义的符号,它无法打开库。有问题的符号位于静态库中。
我真正难以理解的是为什么它在命令行上有效,但在我使用 dlopen()
和运行时时却不起作用。
我还有 3-4 个可以成功使用 dlopen()
的其他共享库 - 所以我知道我使用 dlopen()
的一般过程很好。
我正在使用 dlerror()
来获取未定义符号错误消息。
我看过以下link:
how-to-force-symbols-from-a-static-library-to-be-included-in-a-shared-library-bu
how-to-apply-fvisibility-option-to-symbols-in-static-libraries
我把 -Wl,--whole-archive
的想法联系起来了,但这似乎牵扯太多,并且构建失败并出现了太多警告 - 可能与 google protobuf 东西有关,而且我不确定这是我最终想要采用的方法。
我检查了我的共享库是用 -fPIC
构建的,我不确定静态库是用 -fPIC
构建的还是需要?
我也看过这里:
讨论了如何 link 与 dlopen()
但这是使用 libtools - 我们没有为我们的所有目标提供它,所以我不想使用 libtools。
我真的不确定要采用哪种方法 - 感觉这应该是某个地方的简单修复 - 但正如我所说,我无法理解为什么一种方法有效而另一种方法无效.. .
更新
所以,在 Sam 的评论之后,我开始寻找正确的地方。事实证明,bsp.so 的 makefile 静态 link 只是两个库之一。 该共享库有一个单独的测试器,link 有两个库(因此测试器可以工作),我没有理由怀疑库已损坏......好吧,我学到了很多关于 dlopen 和 linking 等...:o
当您 link 具有共享库的可执行文件时,来自可执行文件的未解析符号引用必须由共享库解析,否则 link 失败。
当您 link 一个共享库时,不需要共享库本身的所有未解析符号都必须由它 link 与之相关的任何其他共享库解析;因此,当您 link 将共享库放在一起时,可能会从共享库本身中得到未解析的符号。
将可执行文件与共享库链接成功,因为可执行文件中所有未解析的符号都由共享库解析;但由于来自共享库本身的未解析符号引用,可执行文件将无法加载。或者,dlopen
()ing 共享库会产生相同的错误。
dlopen
手册页还介绍了几个可用于控制此行为的可选标志。