如何在Linux上加载共享库延迟

我一直在寻找一种方法来创build一个共享库(让我们命名库“ libbar.so ”) 延迟加载到Linux上,它应该只有一个链接器的帮助下实现,而不是修改任何写在源代码上的东西C ++; 我的意思是我不想在父库的源代码中调用dlopen()dlsym() (我们将其命名为“ libfoo.so ”)来调用libbar.so的函数,因为它们会使源代码变得混乱,维护过程困难。 (简而言之,即使在Linux上,我也希望继续使用Visual Studio的/ DELAYLOAD选项)

无论如何,到目前为止,我在互联网上发现了一些与我的问题有关的不确定的信息,所以如果能得到你们所有人的回答,我们将会非常高兴地回答以下问题,以使信息清晰。

  1. GNU ld是否支持Linux上的延迟加载机制?
  2. 如果没有,那么Clang呢?
  3. dlopen()系列是在Linux上加载共享库延迟的唯一方法吗?

我testing了通过-zlazy标志GCC(g ++)的path到库,它似乎接受的标志,但行为没有看起来使libbar.so延迟加载(没有libbar.so ,我期待有一个第一次调用libbar.so时出现exception,但在进入libfoo.so之前实际发生exception)。 另一方面,铿锵(铿锵++)留下一个警告,它忽略了选项标志。

最好的祝福,

Solutions Collecting From Web of "如何在Linux上加载共享库延迟"

延迟加载不是运行时功能。 MSVC ++在没有Windows帮助的情况下实现了它。 而像dlopen是Linux上唯一的方法, GetProcAddress是Windows上唯一的运行时方法。

那么,什么是延迟加载呢? 这很简单:任何对DLL的调用都必须经过一个指针(因为你不知道它将在哪里加载)。 这总是由编译器和链接器为您处理。 但是在延迟加载时,MSVC ++最初将这个指针设置为一个为您调用LoadLibraryGetProcAddress的存根。

Clang可以在没有ld帮助下做同样的事情。 在运行时,这只是一个普通的dlopen调用,而Linux不能确定Clang是否插入了它。

这种功能可以使用代理设计模式以便携的方式实现。

在代码中,它可能看起来像这样:

 #include <memory> // SharedLibraryProxy.h struct SharedLibraryProxy { virtual ~SharedLibraryProxy() = 0; // Shared library interface begin. virtual void foo() = 0; virtual void bar() = 0; // Shared library interface end. static std::unique_ptr<SharedLibraryProxy> create(); }; // SharedLibraryProxy.cc struct SharedLibraryProxyImp : SharedLibraryProxy { void* shared_lib_ = nullptr; void (*foo_)() = nullptr; void (*bar_)() = nullptr; SharedLibraryProxyImp& load() { // Platform-specific bit to load the shared library at run-time. if(!shared_lib_) { // shared_lib_ = dlopen(...); // foo_ = dlsym(...) // bar_ = dlsym(...) } return *this; } void foo() override { return this->load().foo_(); } void bar() override { return this->load().bar_(); } }; SharedLibraryProxy::~SharedLibraryProxy() {} std::unique_ptr<SharedLibraryProxy> SharedLibraryProxy::create() { return std::unique_ptr<SharedLibraryProxy>{new SharedLibraryProxyImp}; } // main.cc int main() { auto shared_lib = SharedLibraryProxy::create(); shared_lib->foo(); shared_lib->bar(); }