链接两个具有相同符号的共享库

53

我与两个不同的共享库链接。这两个库定义了一些具有相同名称但实现不同的符号。我无法使每个库在另一个库之上使用自己的实现。

例如,这两个库都定义了一个全局函数bar(),每个库都从内部调用它。库1从foo1()中调用它,而库2从foo2()中调用它。

Lib1.so:

T bar
T foo1()     // calls bar()

Lib2.so:

T bar
T foo2()     // calls bar()

如果我将应用程序与Lib1.so链接,然后是Lib2.so,即使调用foo2(),也会调用来自Lib1.so的bar实现。另一方面,如果我将应用程序与Lib2.so链接,然后是Lib1.so,则始终从Lib2.so调用bar。
有没有办法使库始终优先使用自己的实现而不是其他任何库?
3个回答

58

有几种解决方法:

  • 向链接器传递-Bsymbolic-Bsymbolic-functions。这具有全局影响:可以将可以解析为库中符号的全局符号引用(函数类型的-Bsymbolic-functions)解析为该符号。使用此方法,您失去了使用LD_PRELOAD对这些符号进行内部库调用的能力。 符号仍在导出,因此它们可以从库外部引用。

  • 使用版本脚本将符号标记为库的local,例如使用以下内容:{local: bar;};并将--version-script=versionfile传递给链接器。 符号不会导出。

  • 使用适当的可见性标记符号(GCC可见性信息页面),其将是hiddeninternalprotectedprotected可见度符号将作为.protected导出hidden符号不导出internal符号不导出,您会妥协并不直接通过函数指针从库外部调用它们。

您可以使用objdump -T检查哪些符号已导出。


2
你好,请问这个也适用于clang吗? - Max Raskin

5
你需要创建两个“包装器”共享库,分别对应你现有的两个库。每个库都应该使用--dynamic-list选项构建,列出只有少量不冲突的符号来定义API。你还需要使用-Bsymbolic选项来避免任何全局组合。
最好通过dlopen和适当的选项访问生成的库,这样会减少一些压力。

1
非常感谢!对于我来说,仅使用-Bsymbolic选项(使用-Wl选项传递给链接器)进行共享库链接即可解决问题。 - drewag

2

解决此问题的另一种方法是使用宏更改命名空间。

先决条件

  • 所有元素(函数、类、全局变量等)都在一个命名空间中。
  • 该库不会在头文件中大量依赖宏。

解决方案

  • When compiling the library, define macro with namespace name to define it to something different. For example if the namespace is LibNS, use -DLibNS=LibNSv1 for one case and -DLibNS=LibNSv2 for the other.
  • When using libraries in the code, define macro according your current situation;

    #define LibNS LibNSv1
    #include "my_lib.h"
    #undef LibNS
    

为什么要使用这个解决方案而不是其他的解决方案

  • 当有问题的库在头文件中被使用(例如模板、内联等)时,当您将它们包含在可执行文件的代码中时,解析器无法确定这些函数应该从Lib1.so还是Lib2.so中调用。
  • 您的编译器对其他解决方案支持较差/没有支持(不应该发生在我们的intel/amd 32/64位CPU上,但从Google搜索结果来看,一些其他平台可能存在该问题)。

可能出现的问题

  • 在一个cpp文件中同时使用两个版本可能会有问题;#include "my_lib.h"可能使用宏来防止多次包含并取消定义以避免这种情况可能会导致许多不同的问题(库的作者可能会在未来更改宏名称,头文件定义了其他宏等)。
  • 名称LibNS可能已经用于库中的其他内容(变量、函数等);在这种情况下,该名称也将更改为LibNSv1LibNSv2。这可能会导致其他问题,具体取决于库及其使用方式。

  • 这不是要取代当前被接受的答案(来自ninjalj;随意复制粘贴),而是用另一种方法扩展它。
  • 我发布这个答案的主要原因是今天我遇到了这个问题,但由于有问题的代码在头文件中,所以答案没有帮助。
  • 我的来源:https://spin.atomicobject.com/2014/06/03/static-linking-c-plus-plus/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接