19

実際の実装コードを取得した実際の .dll ファイル内の情報を参照するだけでは、なぜリンカは自分の仕事を実行できないのでしょうか? つまり、暗黙のリンクを行うためにリンカがまだ .lib ファイルを必要とするのはなぜですか?

このようなリンクには、エクスポート テーブルと相対アドレス テーブルだけで十分ではありませんか?

とにかく.libスタブ/プロキシファイルなしで.dllのみを使用して暗黙的なリンクを行うことができるものはありますか?

Windows実行可能ローダーは、プログラムに代わってLoadLibrary/LoadLibraryEx呼び出しを実行するだけだと思いました(したがって、暗黙的なリンクという名前です)。これは、明示的なリンクとの主な違いです。それが本当なら、.libなしで明示的にそれを行うことは、それがなくても暗黙的に実行可能であることを示しているはずですよね? または私はナンセンスを言っているだけですか?

4

1 に答える 1

10

いくつかの理由が考えられます。

  • .lib ファイルを使用すると、正しい SDK がインストールされていれば、システムにあるものとは異なるバージョンの DLL 用にビルドできます。
  • コンパイラとリンカはクロスプラットフォーム コンパイルをサポートする必要があります - 32 ビット プラットフォームで 64 ビット ターゲット用にビルドし、その逆も同様で、正しいアーキテクチャ DLL が存在しない可能性があります。
  • .lib ファイルを使用すると、実装の特定の部分を「隠す」ことができます。.lib には表示されないが、GetProcAddress を介して検出できるプライベート エクスポートを持つことができます。また、序数のエクスポートを行うこともできます。この場合、エクスポートされたフレンドリ名はありませんが、.lib にはフレンドリ名があります。
  • ネイティブ DLL には厳密な名前がないため、間違ったバージョンの DLL を取得する可能性があります。
  • そして最も重要なことは、この技術が 1980 年代に設計されたことです。今日設計されていれば、おそらくあなたが説明したものに近いでしょう。たとえば、.NET では、ターゲット アセンブリを参照するだけで、それを使用するために必要なものがすべて揃っています。

DLL のみを使用して暗黙的なリンクを行う方法を知りません。クイック検索でいくつかのツールが見つかりましたが、私はそれらのいずれも使用していません。

この場合、使用する必要がある関数を含む別のソース ファイルを作成し、必要に応じて DLL を動的にロードしてバインドします。例えば:

// using global variables and no-error handling for brevity.

HINSTANCE theDll = NULL;
typedef void (__stdcall * FooPtr)();
FooPtr pfnFoo = NULL;
INIT_ONCE initOnce;

BOOL CALLBACK BindDLL(PINIT_ONCE initOnce, PVOID parameter, PVOID context)
{
    theDll = LoadLibrary();
    pfnfoo = GetProcAddress(dll, "Foo");

    return TRUE;
}

// Export for foo
void Foo()
{
    // Use one-time init for thread-safe lazy initialization
    InitOnceExecuteOnce(initOnce, BinDll, NULL, NULL)
    pfnFoo();
}
于 2009-08-18T23:07:40.793 に答える