如何从dlopen'd库L中访问程序P中的静态变量?

时间:2013-02-20 23:47:21

标签: c++ linux gcc

我有一个库(L),它由程序(P)使用dlopen动态加载。 L实现了一个插件接口,因此回调它的父节点以获得一些功能。

Inside P是一个动态创建线程池对象A的单例对象。 我需要从L获得A。

然而,因为单例通过使用静态变量来工作,所以当加载L时,它最终会创建它自己的实例,这在某些情况下会很好但是我想要在P中创建的实例。有没有办法绕过这个?

2 个答案:

答案 0 :(得分:1)

你不应该在L中有static A.让P将A的地址传递给L,即L.init(&A)

答案 1 :(得分:1)

声明为static的文件范围名称具有内部链接。内部链接意味着它们对其他翻译单元是不可见的,即使在没有任何动态库的“经典”链接模型中也是如此。鉴于即使对于同一可执行文件中的其他翻译单元也看不到静态,因此期望从附加的动态库中看到它们是不合理的。

您必须考虑使用外部动态符号实现必要链接的方法。也许单身人士根本不能拥有内部名称,但必须有外部名称。

L正在创建自己的对象实例,不仅因为该对象是静态的,而且因为您已将链接到L的线程池模块定义了该单例和线程池函数。即使对象具有外部名称,也会发生这种情况,具体取决于库的链接方式。

您必须选择线程池服务所在的单个对象,然后确保它只驻留在那里。你的项目是不是有一个实用程序库,你可以坚持这种事情?

可以遵守提供线程池API的程序可执行文件P的模型。这真是一回事。程序P是另一个动态对象,有效地充当线程池模块的库,它提供给自己和其他共享对象。

无论该线程池模块的位置如何,请确保您没有将该模块的副本静态链接到其他对象:它只存在于一个位置。

如果线程池单例的外部名称是该API的一部分(每个人都知道它的文档名称并直接使用它,将该全局池传递给API函数),那么该名称应该是外部的,并在头文件中声明。

如果单例是私有的,那么你必须考虑一些隐藏它的方法,比如在函数调用中隐含它(只有一个线程池,那就是那个)或者抽象访问它有点(提供ensure_thread_pool)函数,如果一个线程池不存在,它会创建一个线程池,或者以线程安全的方式返回先前创建的线程池。

想一想:为什么不这样做,例如,stdinstdout有这个问题?为什么不是每个库都实例化自己的stdout流并在该流上调用自己的fprintf函数?显然,为什么这些东西生活在一个地方:C库。他们的副本不住在其他地方;其他地方只需通过动态符号引用它们。