15

呼び出し規約を次のように指定するアプリケーション (fyi: mIRC) で動作するように、dll の簡単なテスト関数をエクスポートしようとしていました。

int __stdcall test_func(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)

アプリケーションからこれを呼び出すには、test_funcを使用しますが、名前マングリングのために、思ったほど単純ではないことに気付きました。

ここでの同様のトピックを通じて、extern "C"を__declspec(dllexport)と組み合わせて使用​​することは、モジュール定義 (.def) へのマングリングを削除する同等の (ある程度) 方法であることがわかりました。ただし、extern/dllexport メソッドを使用する場合、私の関数 (例として) は常に_test_func@numbers ですが、.def は、エクスポートする必要のあるアプリケーションで使用するために必要なすべてのマングリングを削除しました。

誰かがこれがなぜなのか説明してもらえますか? 私は2つの方法に興味があります。ありがとう!

4

2 に答える 2

15

extern "C"stdcall とは何の関係もありません。C++ の名前マングリング (別名タイプ セーフ リンケージ、シンボル名に型情報を含める) が無効であることを宣言するだけです。C 呼び出し規約または stdcall 呼び出し規約のどちらを使用するかに関係なく、これを使用する必要があります。

stdcall 呼び出し規約では、呼び出し先がスタックからパラメーターを削除します。これを安全にするために、エクスポートされた名前には、呼び出し先がスタックから削除するバイト数が含まれています。

エクスポート先のアプリケーションが@number名前に接尾辞を追加しないことを要求する場合、それはおそらく C 呼び出し規約を想定していることを意味します。したがって、関数を として宣言するのをやめるべきです__stdcall。として宣言するとdeclspec(dllexport)、DLL で装飾されていない名前を取得する必要があります。

DEF ファイルでは、任意の関数を呼び出すことができます。追加のチェックは実行されません。

于 2010-12-28T23:40:35.483 に答える
13

dllexport/import は、GetProcAddress を使用する古い C ライブラリではなく、それ自体で再度ロードされるように設計されています。あなたが見たマングリングは、すべての Microsoft コンパイラが長い間 __stdcall 関数に対して行ってきたことです。ほとんどの場合、ターゲットは __stdcall ではなく __cdecl 関数を期待していますが、そうでない場合は、.def ファイルを使用して名前のマングルを明確に解除する必要があります。

于 2010-12-28T23:44:33.560 に答える