dlopen和隐式库加载:同一个库的两个副本

时间:2012-09-13 18:20:21

标签: c++ c linux

我有3件事:开源应用程序(我们称之为APP), 闭源共享库(我们称之为OPENGL) 和OPENGL的开源插件(我们称之为PLUGIN)[也是共享库] 操作系统:Linux
需要在APP和PLUGIN之间共享数据, 所以APP与PLUGIN联系,当我运行时, 系统自动加载
之后APP调用eglInitialize属于OPENGL, 之后,此功能再次加载PLUGIN。

之后我在APP内存中有两份PLUGIN。

我知道因为PLUGIN有全局数据,经过调试 我看到有两份全局数据。

那么问我如何解决这个问题呢? 我想要APP和OPENGL使用的一个PLUGIN实例。 我无法更改OPENGL库。

2 个答案:

答案 0 :(得分:2)

这显然在很大程度上取决于库正在做什么,但通常一些解决方案应该是可能的。

首先请注意,通常如果多次加载具有相同名称的共享库,它将继续使用相同的库。这个coruse主要适用于通过标准加载/链接机制加载。如果库自己调用dlopen,它仍然可以获得相同的库,但它取决于dlopen的标志。尝试阅读dlopen上的文档,以了解它是如何工作的以及如何操作它。

您还可以尝试在链接器命令中更早地定位PLUGIN,以便首先加载它,从而避免以后加载双重加载。如果你必须动态加载PLUGIN,这显然无济于事。您还可以检查LD_PRELOAD是否可以解析链接顺序。

作为最后的手段,您可能不得不求助于使用LD_LIBARY_PATH并从真实的接口库中放入接口库。这个将简单地将调用传递给真实的,但将拦截重复的负载并将它们分流到先前的负载。

这只是一个需要考虑的大方向。您的实际答案将在很大程度上取决于您的代码以及其他共享库的功能。始终首先研究链接器加载顺序,因为它最容易检查,然后在进入其他选项之前执行dlopen标记。

答案 1 :(得分:1)

我怀疑OPENGL正在使用RTLD_LOCAL标志加载PLUGIN。这个 通常是你加载一个插件时想要的,所以这就是多个 插件不冲突。

我们在Java下加载代码遇到了类似的问题:我们加载了一个 十几个不同的模块,他们无法与一个人沟通 另一个。我们的解决方案可能适合您:我们写了一个 插件的包装器,并告诉Java包装器是插件。 然后,该插件使用dlopen加载其他每个共享对象 与RTLD_GLOBAL。这在插件之间起作用。我不确定 然而,将允许插件返回主要(但我认为它 应该)。和IIRC,在连接main时你需要特殊选项 它的符号可用。我认为Linux主要处理符号 好像main已加载RTLD_LOCAL否则。 (也许 --export-dynamic?已经有一段时间了,因为我不得不这样做,而且我 记不清楚。)