Windowsで、MSVCのDLLプロジェクトでC/C++コードをコンパイルすると、2つのファイルが得られます。
MyDll.dll
MyDll.lib
私が理解している限り、MyDll.lib
には、dll内の関数の場所を示すポインタテーブルの種類が含まれています。このDLLを使用するとき、たとえばexeファイルで、リンケージ中にMyDll.lib
がexeファイルに埋め込まれるため、実行時にMyDll.dll
内の関数の場所を「認識」し、それらを使用できます。
しかし、Linuxで同じコードをコンパイルした場合、oneMySo.so
なしのファイルMySo.a
(lib
ファイル)では、リンク中に何も埋め込まれていない場合、Linuxの実行可能ファイルは、関数がMySo.so
のどこにあるかをどのようにして知るのでしょうか。
Linuxでは、リンカ(動的リンカではない)がリンク時に指定された共有ライブラリを検索し、実行可能ファイル内にそれらへの参照を作成します。動的リンカーがこれらの実行可能ファイルをロードすると、必要な共有ライブラリーがメモリーにロードされ、シンボルが解決されるため、バイナリーを実行できます。
MySo.a
が作成された場合、実際には、Windowsで使用される「シンボルルックアップテーブル」ではなく、バイナリに直接リンクされるシンボルが含まれます。
rustyxの答え Windowsでのプロセスを私よりも詳しく説明しています。私がWindowsを使用してから久しぶりです。
MSVCリンカーは、オブジェクトファイル(.obj)とオブジェクトライブラリ(.lib)をリンクして、.EXEまたは.DLLを生成できます。
DLLとリンクするには、MSVCでのプロセスは、C関数名とDLLのエクスポートテーブルの間の接着剤として機能する、いわゆるインポートライブラリ(.LIB)を使用することです(DLL =関数は名前または ordinal でエクスポートできます。後者は、文書化されていないAPIでよく使用されていました)。
ただし、ほとんどの場合、DLLエクスポートテーブルにはすべての関数名が含まれているため、インポートライブラリ(.LIB)には冗長な情報( "import function ABC ->エクスポートされた関数ABC "など)。
既存の.DLLから.LIBを generate にすることも可能です。
他のプラットフォームのリンカーにはこの「機能」がなく、ダイナミックライブラリと直接リンクできます。
あなたが見ている違いは実装の詳細です-LinuxとWindowsの両方のフードの下で同様に動作します-あなたは実行可能ファイルに静的にリンクされているスタブ関数をコード呼び出しし、このスタブはその後必要に応じてDLL/shlibをロードします(-の場合) 遅延読み込み 、それ以外の場合、プログラムの起動時にライブラリが読み込まれます)および(最初の呼び出しで)GetProcAddress
/dlsym
を介してシンボルを解決します。
唯一の違いは、Linuxではこれらのスタブ関数(PLTスタブと呼ばれます)が生成されます動的にアプリを動的ライブラリ(ライブラリにそれらを生成するのに十分な情報が含まれています)にリンクすると、 DLL自体が別の.lib
ファイルに作成されると、代わりに生成されます。
2つのアプローチは非常に似ているため、LinuxでWindowsインポートライブラリを模倣することが実際に可能です( Implib.so プロジェクトを参照)。
Linuxでは、MySo.so
をリンカに渡すと、リンクフェーズに必要なものだけを抽出し、その参照をMySo.so
は実行時に必要です。