如何找到库以使用dlopen动态加载它们

时间:2011-07-15 08:52:26

标签: c++ cmake dlopen dynamic-loading

在我正在开发的项目中,我们提供了动态加载其他功能的可能性。为此,我们使用dlopen。

为了找到这个库,我们有一些我们称之为模块路径的东西。我们有一个默认路径,共享库(很多都是附带的)。

目前我们有两个默认路径:首先查看共享库的构建目录,然后查看安装目录。这是因为它也应该可以在不安装的情况下运行应用程序(因此在这种情况下,它需要首先在构建目录中查找)。

现在问题是,如果用户从源构建应用程序并使用make install安装它,则默认情况下会加载她的构建目录中的库。这将导致崩溃。因此,只有在用户之后删除或重命名构建目录时,它才有效。

没问题:是否有一个技巧(通过C ++或构建系统)来了解应用程序是否已安装。问题是,功能是在共享库中实现的,搜索模块的实现方式也适用于链接到我们库的其他应用程序(因此我们不能依赖可执行文件的路径)。我们使用CMake作为构建系统。

为了使情况更加困难,该解决方案必须适用于Windows,Linux和Mac OS X.

编辑:

我进一步调查,问题更复杂。情况就是这样:

  • 有一个小的可执行文件
  • 此外还有一个“主”库main.so
  • 然后有一个动态加载的库lib.so
  • lib.so链接反对main.so

问题是,lib.so在其rpath的build目录中具有main.so的绝对路径。感谢@MSalters的提示,我现在能够确保加载正确版本的lib.so(安装目录中的那个),但由于它在rpath中有构建路径,因此它加载了错误的主.so(所以实际上在内存中有两个main.so副本 - 这会让事情变得混乱)。

有没有办法从库中删除对构建路径的引用?我尝试了与rpath相关的所有cmake选项,但没有成功

2 个答案:

答案 0 :(得分:1)

您无法检查可执行文件本身的位置吗?如果它在构建目录中,请使用构建库 - 如果它在安装中,请使用install?

getcwd()在所有这些平台上具有等价物,但它可能不是您想要的 - 它取决于您运行可执行文件的方式。

为了让流程的位置与系统相关,我认为,但它不应该太难以包装。

答案 1 :(得分:0)

安装的版本不应该在rpath中有build目录。

您可能希望进行两次链接(一次用于构建版本,一次用于已安装的版本)。通常,在* nix系统上,安装的二进制文件有一些静态路径,它试图找到插件。您可以定义一些环境变量(或命令行参数)来为构建执行重载它(并使用包装器脚本在构建环境中设置它)。

检查一些项目如何解决(例如Firefox)。

我对Windows系统了解不多,但我认为这样做的标准方法是在与可执行文件相同的目录中搜索插件。