遅延読み込みはランタイム機能ではありません。 MSVC++ は、Windows の助けを借りずに実装しました。そして dlopen
のように Linux では GetProcAddress
が唯一の方法です。 Windows で唯一のランタイム メソッドです。
それでは、遅延読み込みとは何ですか?それは非常に簡単です:DLL への呼び出しはすべてポインターを経由する必要があります (どこにロードされるかわからないため)。これは常にコンパイラとリンカーによって処理されます。ただし、遅延読み込みでは、MSVC++ は最初にこのポインターを LoadLibrary
を呼び出すスタブに設定します。 と GetProcAddress
あなたのために。
Clang は ld
の助けがなくても同じことができます .実行時は普通の dlopen
です 呼び出し、Linux は Clang がそれを挿入したと判断できません。
MSalters の回答に追加するには、dlopen
しようとする小さな静的スタブ ライブラリを作成することで、Linux での遅延読み込みに対する Windows のアプローチを簡単に模倣できます。 その関数のいずれかへの最初の呼び出しで必要なライブラリ (診断メッセージを発行し、dlopen が失敗した場合は終了する) と、そのライブラリへのすべての呼び出しを転送します。
このようなスタブ ライブラリは、手動で記述したり、プロジェクト/ライブラリ固有のスクリプトで生成したり、ユニバーサル ツール Implib.so で生成したりできます:
$ implib-gen.py libxyz.so
$ gcc myapp.c libxyz.tramp.S libxyz.init.c ...
この機能は、プロキシ デザイン パターンを使用して移植可能な方法で実現できます。
コードでは次のようになります:
#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();
}