P/Invoke で C# cdecl
と C __stdcall
が共存する理由
C# と C の間の P/Invoke 相互運用では、C# 関数が cdecl
呼び出し規約を使用し、C の対応する関数が __stdcall
シグネチャを使用することがよくあります。この不一致は、歴史的に今日まで続いている呼び出し規約の選択に起因しています。
__stdcall
: Windows 関数の呼び出し元のクリーンアップ
__stdcall
16 ビット Pascal 呼び出し規則から継承され、Windows API 関数と COM のデフォルトの呼び出し規則です。これにより、呼び出し先 (呼び出される関数) が実行後にスタックをクリーンアップし、リソースに制約のある環境でスタックをよりコンパクトにすることができます。ただし、この利点には、呼び出し元と呼び出し先が予期する引数の数が一致しない場合、スタックの不均衡が生じるリスクが伴います。
__cdecl
: 可変個引数関数の呼び出し元のクリーンアップ
__cdecl
は、printf()
や scanf()
など、可変数の引数を持つ関数に対する C の標準呼び出し規則です。この規則では、呼び出し元は渡された引数の数を知っているため、スタックのクリーンアップの責任は呼び出し元にあります。 C# の [DllImport]
宣言で CallingConvention.Cdecl
を指定するのを忘れるのはよくある落とし穴です。
__thiscall
: C メソッド
__thiscall
は特に C を指し、クラスのインスタンス メソッドで非表示の this
ポインターの受け渡しを処理するために使用されます。これは __cdecl
に似ていますが、.NET P/Invoke マーシャラーはこれをサポートしていないため、pinvoke C コードでの使用には適していません。
概要
C# の 呼び出しと C の cdecl
シグネチャの共存は、これらの歴史的な呼び出し規約と各言語の特定の要件の結果です。これらの規則と、__stdcall
の [DllImport]
および EntryPoint
属性を正しく理解することは、正しい P/Invoke 機能を確保し、スタックの不均衡などの潜在的な問題を回避するために重要です。 ExactSpelling
以上がC# `cdecl`呼び出しとc` __stdcall`署名がp/invokeで共存するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。