静的ライブラリ (.a) は、リンカーによって生成される最終的な実行可能ファイルに直接リンクできるライブラリであり、その中に含まれており、実行可能ファイルが展開されるシステムにライブラリを含める必要はありません。
共有ライブラリ (.so) リンクされているが最終的な実行可能ファイルに埋め込まれていないライブラリであるため、実行可能ファイルの起動時にロードされ、実行可能ファイルが展開されるシステムに存在する必要があります。
windows のダイナミック リンク ライブラリ (.dll) Linux の共有ライブラリ (.so) に似ていますが、OS に関連する 2 つの実装にはいくつかの違いがあります (Windows と Linux):
DLL export と internal の 2 種類の関数を定義できます。エクスポートされた関数は、定義されている DLL 内からだけでなく、他のモジュールからも呼び出されることを意図しています。通常、内部関数は、それらが定義されている DLL 内からのみ呼び出されることを意図しています。
SO Linux 上のライブラリでは、すべてのシンボルが問い合わせプロセスで使用できるため、エクスポート可能なシンボルを示す特別なエクスポート ステートメントは必要ありません。
私は常に、DLL と共有オブジェクトは同じものを表す別の用語だと考えてきました。Windows では DLL と呼ばれますが、UNIX システムでは共有オブジェクトであり、動的にリンクされたライブラリという一般的な用語で両方をカバーします ( UNIX では dlopen()
と呼ばれる .so を開く 「動的ライブラリ」の後)。
それらは実際にはアプリケーションの起動時にのみリンクされますが、ヘッダー ファイルに対する検証の概念は正しくありません。ヘッダー ファイルは、ライブラリを使用するコードをコンパイルするために必要なプロトタイプを定義しますが、リンク時にリンカーはライブラリ自体の内部を調べて、必要な関数が実際にそこにあることを確認します。リンカーは、リンク時にどこかで関数本体を見つける必要があります。そうしないと、エラーが発生します。あなたが正しく指摘したように、プログラムがコンパイルされてからライブラリ自体が変更された可能性があるため、実行時にもそれを行います。これが、ABI の変更が古いバージョンに対してコンパイルされた既存のプログラムを破壊するものであるため、ABI の安定性がプラットフォーム ライブラリで非常に重要である理由です。
静的ライブラリは、プロジェクトのコンパイルの一部として自分でビルドするものと同じように、コンパイラから直接出力されるオブジェクト ファイルの単なるバンドルであるため、それらはまったく同じ方法で取り込まれてリンカーに供給され、未使用のビットは
Windows の DLL の詳細を詳しく説明して、ここ *NIX の世界にいる友人たちに謎を解き明かす手助けをすることができます...
DLL は共有オブジェクト ファイルのようなものです。どちらもイメージであり、それぞれの OS のプログラム ローダーによってメモリにロードする準備ができています。画像には、リンカーとローダーが必要な関連付けを行い、コードのライブラリを使用するのに役立つさまざまなメタデータが付随しています。
Windows DLL にはエクスポート テーブルがあります。エクスポートは、名前またはテーブルの位置 (数値) で行うことができます。後者の方法は「古い方法」と見なされ、はるかに脆弱です。DLL を再構築し、テーブル内の関数の位置を変更すると、惨事に終わりますが、エントリ ポイントのリンクが名前によるものである場合、実際の問題はありません。そのため、問題としてそれを忘れてください。ただし、サードパーティ ベンダー ライブラリなどの「恐竜」コードを使用する場合は、そこにあることに注意してください。
Windows DLL は、EXE (実行可能アプリケーション) の場合と同じように、コンパイルとリンクによって構築されますが、DLL は、SO がアプリケーションによって使用されることを意図しているように、スタンドアロンではありません。リンク時のバインディング (SO への参照はアプリケーション バイナリのメタデータに埋め込まれ、OS プログラム ローダーは参照された SO を自動ロードします)。 SO が他の SO を参照できるように、DLL は他の DLL を参照できます。
Windows では、DLL は特定のエントリ ポイントのみを使用可能にします。これらは「輸出」と呼ばれます。開発者は、特別なコンパイラ キーワードを使用してシンボルを外部から (他のリンカーやダイナミック ローダーから) 見えるようにするか、エクスポートをモジュール定義ファイルにリストして、DLL 自体がリンク時に使用されるようにすることができます。作成中です。最近の慣習では、シンボル名をエクスポートするキーワードで関数定義を装飾します。また、そのシンボルを現在のコンパイル単位外の DLL からインポートされるものとして宣言するキーワードを含むヘッダー ファイルを作成することもできます。詳細については、キーワード __declspec(dllexport) および __declspec(dllimport) を調べてください。
DLL の興味深い機能の 1 つは、標準の "ロード/アンロード時" ハンドラー関数を宣言できることです。 DLL がロードまたはアンロードされるたびに、DLL は場合によっては初期化またはクリーンアップを実行できます。これは、デバイス ドライバーや共有オブジェクト インターフェイスなどのオブジェクト指向のリソース マネージャーとして DLL を持つことにうまく対応します。
開発者がビルド済みの DLL を使用したい場合、DLL 開発者が DLL を作成したときに作成した「エクスポート ライブラリ」(*.LIB) を参照するか、実行時に DLL を明示的にロードして、 LoadLibrary() および GetProcAddress() メカニズムを介した名前によるエントリ ポイント アドレス。ほとんどの場合、LIB ファイル (DLL のエクスポートされたエントリ ポイントのリンカー メタデータが含まれているだけ) に対するリンクは、DLL が使用される方法です。動的ローディングは通常、プログラムの動作に「ポリモーフィズム」または「実行時の構成可能性」を実装するために予約されています (アドオンまたは後で定義される機能、別名「プラグイン」へのアクセス)。
Windows のやり方では、混乱を招くことがあります。システムは .LIB 拡張子を使用して、通常の静的ライブラリ (POSIX *.a ファイルなどのアーカイブ) と、リンク時にアプリケーションを DLL にバインドするために必要な「エクスポート スタブ」ライブラリの両方を参照します。したがって、*.LIB ファイルに同じ名前の *.DLL ファイルがあるかどうかを常に確認する必要があります。そうでない場合は、*.LIB ファイルが静的ライブラリ アーカイブであり、DLL のバインド メタデータをエクスポートしない可能性が高くなります。