MinGW を使用して、サードパーティの dll から外部 C 関数を使用するプログラムをコンパイルしようとしているようです。これらの外部関数を、MinGW のgnu ldリンカーが使用できる適切なインポート ライブラリにエクスポートする方法がありますが、それには.def定義ファイルの作成が必要です。これの利点は、適切なインポート ライブラリを作成すると、--add-stdcall-aliasまたは--kill-atインポート ライブラリにコンパイラとリンカーが期待するシンボルが含まれるため、スイッチをいじる必要がないことです。
これを行う手順の大まかな概要は次のとおりです。
- コンパイラ
dlltool.exeと同じディレクトリに含まれるツール呼び出しが必要です。MinGW/bin
- インポートするすべての外部関数をリストした定義ファイル (*.def) を作成する必要があります。
- 作成した .def ファイルを入力として渡す dlltool を実行して、インポート ファイル スタブ (*.a) を作成します。
- プロジェクトをビルドするときに、新しく作成したインポート ファイル *.a をリンカーに渡して、シンボルを適切に解決できるようにします。
定義ファイルは次のようになります。
;Run the dlltool like this:
;dlltool -k -d third_party.def -l libthird_party.a
LIBRARY third_party.dll
EXPORTS
dll_function1@0
dll_function2@8
dll_function3@16
; ...
dll_function_n@24
注意すべき重要な点がいくつかあります。このEXPORTSセクションでは、エクスポートされたシンボル/関数を、ツールチェーンが期待するのと同じ名前で装飾された形式でリストする必要があります。この場合、MinGW コンパイラと ld リンカは、__stdcallC 関数に「@」の後に引数のバイト数が追加されることを期待します。注目すべき 2 番目の重要な点は、'@' を削除することです。これは、既に見dlltool -kたオプションと同じことを行います。--kill-atこれの最終結果は、正しい内部名装飾を備えたインポート ライブラリを持っているため、物事は適切に解決され、その内部名は、サードパーティの dllで見つかったエクスポートされた可視名にマップされます。
言及する必要がある最後の 1 つのこと。例全体を通して、dll 内の装飾されていない名前が を使用していると想定し__stdcallていましたが、これは必ずしも正しくありません。次のグラフ (ここから取得) は、さまざまなコンパイラがどのように__cdecl対装飾を異なるかを示しています__stdcall。
MSVC DLL
Call Convention | (dllexport) | DMC DLL | MinGW DLL | BCC DLL
----------------------------------------------------------------------------
__stdcall | _Function@n | _Function@n | Function@n | Function
__cdecl | Function | Function | Function | _Function
呼び出し規則が適切に一致していることを確認するか、スタックの破損や不可解なプログラムのクラッシュの危険を冒すかは、ユーザー次第です。