C# P/呼び出し呼び出し規約の不一致のトラブルシューティング
この記事では、プラットフォーム呼び出し (P/Invoke) を使用して C# と C コードの間で対話する場合の一般的な問題について説明します。 ここでは、呼び出し規約の不一致の問題、つまり C# の CallingConvention.Cdecl
と C の __stdcall
に焦点を当てます。
呼び出し規約の説明
32 ビット環境では、呼び出し規約によりパラメーターの受け渡し、スタック ストレージ、クリーンアップが規定されます。主な規則には以下が含まれます:
__stdcall
: 呼び出し元は引数をプッシュします。呼び出し先はスタックをクリーンアップします。 Windows API および COM によって使用されます。__cdecl
: 呼び出し元は引数をプッシュし、スタックをクリーンアップします。 C の標準__fastcall
: 一部の引数にレジスタを使用し、速度は向上する可能性がありますが、互換性は低下します。__thiscall
: __cdecl
と似ていますが、C メンバー関数の "this" ポインターを処理します。__clrcall
: 他の要素のバランスをとるマネージド呼び出し規約で、スタックの問題を防ぎます。コード例の分析
C 関数について考えてみましょう。
<code class="language-c++">extern "C" int __stdcall InvokedFunction(int);</code>
それに対応する C# P/Invoke:
<code class="language-csharp">[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int InvokedFunction(IntPtr intArg);</code>
コンベンション・クラッシュ
この問題は、C# の CallingConvention.Cdecl
が C の __stdcall
と競合することに起因します。これはスタックの不均衡につながります。 __stdcall
は (Windows API の普及により) P/Invoke のデフォルトであることが多いですが、__cdecl
C コードとのインターフェースには明示的な規約仕様が必要です。
解決策
解決策は簡単です。C# の呼び出し規約を C の呼び出し規約に合わせます。
<code class="language-csharp">[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Stdcall)] private static extern int InvokedFunction(int intArg); // Note: IntPtr changed to int</code>
重要なポイント
言語間の相互運用性を成功させるには、呼び出し規約を理解することが不可欠です。 規則を一致させることでスタック エラーが防止され、C# と C のスムーズな統合が保証されます。
以上がC#P/CallingConvention.cdecl`を呼び出すとC#P/Invoke Callがc` __stdcall`関数を呼び出すときに失敗するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。