1

次のようにプロトタイプ化されたいくつかの C++ 関数を宣言しました。

extern "C" void __stdcall function();

エクスポートされたサードパーティのdllもいくつかありますfunction()-名前の装飾はまったくありません。undefined reference to function@...MinGW の stdcall @-suffix が原因で、exe または dll をビルドできません。@... プレーン関数名なしでオブジェクトファイルを取得するにはどうすればよいですか?

4

2 に答える 2

6

MinGW を使用して、サードパーティの dll から外部 C 関数を使用するプログラムをコンパイルしようとしているようです。これらの外部関数を、MinGW のgnu ldリンカーが使用できる適切なインポート ライブラリにエクスポートする方法がありますが、それには.def定義ファイルの作成が必要です。これの利点は、適切なインポート ライブラリを作成すると、--add-stdcall-aliasまたは--kill-atインポート ライブラリにコンパイラとリンカーが期待するシンボルが含まれるため、スイッチをいじる必要がないことです。

これを行う手順の大まかな概要は次のとおりです。

  1. コンパイラdlltool.exeと同じディレクトリに含まれるツール呼び出しが必要です。MinGW/bin
  2. インポートするすべての外部関数をリストした定義ファイル (*.def) を作成する必要があります。
  3. 作成した .def ファイルを入力として渡す dlltool を実行して、インポート ファイル スタブ (*.a) を作成します。
  4. プロジェクトをビルドするときに、新しく作成したインポート ファイル *.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

呼び出し規則が適切に一致していることを確認するか、スタックの破損や不可解なプログラムのクラッシュの危険を冒すかは、ユーザー次第です。

于 2012-01-27T11:42:14.680 に答える
4

man ld --enable-stdcall-fixup@ で装飾されていないライブラリに対してリンクするためのオプションを提供します。先頭のアンダースコアが問題になるかどうかはわかりません。試してみる必要があります。

mingw を使用してオブジェクト ファイルまたは DLL を生成し、"@" を含まないエクスポート名が必要な場合--kill-atは、あなたの友人です。

于 2011-11-09T13:34:25.063 に答える