【问题标题】:Two versions of same library in one app同一个库的两个版本在一个应用程序中
【发布时间】:2018-04-23 17:02:07
【问题描述】:

我有同一个共享库的两个版本(具有几乎相同的 API)。我必须在同一个应用程序中使用它们。我知道如何解决标题中的名称冲突——我将像这样导入它们

namespace version1 {
    #include "version1/library.h"
}

namespace version2 {
    #include "version2/library.h"
}

我不知道如何解决链接冲突——库是动态链接的。第一个版本在自定义 lib 文件夹中创建以下结构:

libsomething.so -> libsomething.so.2
libsomething.so.2 -> libsomething.so.0.8.31.1
libsomething.so.0.8.31.1

第二个:

libsomething.so -> libsomething.so.2
libsomething.so.2 -> libsomething.so.0.8.32
libsomething.so.0.8.32

我的目标环境是Linux机器。

上下文:

我有库的来源,但它们是自动下载和编译的,所以我想避免在 CMakeProject 中更改这些库的任何内容,但如果其他选项过于复杂,我可以这样做。我更喜欢在编译后对这些库进行更改的解决方案,例如改名。但是,如果我必须在应用程序代码中做一些复杂的事情来使用这些库,我更喜欢对这些库项目进行更改并维护它们(因为版本可以更改,但总会有两个 - 一个版本可能会永远设置并且从未更新,所以我更愿意更改这个不变的版本)。

【问题讨论】:

  • 命名空间不会解决链接问题,除非您重建两个版本的库,以便函数也在各自的命名空间中定义。更常用的方法是,对于每个动态链接库,设置一个数据结构,其中包含一组指向该库中函数的指针。

标签: c++ compilation linker


【解决方案1】:

我的目标环境是Linux机器。

似乎两个版本的库,基于符号链接,具有相同的SONAME,即libsomething.so.2

这完全排除了将它们链接到同一个可执行文件,并在运行时使用 Linux 的运行时加载程序加载它们。它没有这个能力。

我看到的唯一选项是让您的可执行文件手动加载每个库,使用 dlopen(3) 库调用。之后你需要使用dlsym(3) or dlsymv3(3)在每个加载的库中找到每个函数的地址,并间接调用它。

请注意,dlsym()dlsymv3() 采用每个函数名称的错位版本。由您来决定每个函数的错位名称是什么。

没有人声称这会很容易,但在绝对没有其他选择的情况下这是可行的。

【讨论】:

  • 是否通过将文件名更改为 libsomeghingver1.so.2 和 libsomeghingver2.so.2 之类的名称来更改 so 名称以使其更容易,或者如果我更改 soname,我是否需要重新编译库?跨度>
  • 我在问题的最后添加了一些上下文。
  • 是的,如果您更改库的名称,就足够了。
  • 您能否编辑您的问题,然后告诉我更改库名称后我必须做什么?毕竟,如果我与这​​两个库链接,它们都将具有相同的类和方法。所以如果我打电话给例如obj.f() 来自命名空间 version1,然后链接器仍然不知道它应该从哪个库链接。对于我理想的解决方案是,如果我不必使用 dlsym 使用加载函数,但通常我想编写“普通”函数调用。
  • 不,如果它们具有相同的名称和类,您将无法与它们链接(嗯,您实际上会,但是来自您的可执行文件的引用将仅解析到其中一个库' 符号)。这假定所有名称和类都不同。如果名称和类相同,则基于 dlopen 的方法是唯一的解决方案。
猜你喜欢
  • 2019-11-18
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多