理解 P/Invoke 中的 Cdecl/__stdcall 衝突
P/Invoke 連接 C# 和 C,依賴匹配的呼叫約定來確保正確的參數傳遞和堆疊管理。 當使用預設(通常是 __stdcall
)P/Invoke 約定從 C# 呼叫使用 cdecl
約定的 C 函數時,會出現一個常見問題。
問題的根源
不同的呼叫約定以不同的方式處理堆疊清理:
__stdcall
:廣泛用於 Windows API 和 COM,被呼叫者(C 函數)負責清理堆疊。 __cdecl
:預設的 C 呼叫約定,呼叫者(C# 程式碼)處理堆疊清理。 __thiscall
:用於C成員函數;由於其複雜性,P/Invoke 不直接支援它。 不符的後果
僅將 extern "C"
加入 C 程式碼並在 C# CallingConvention.Cdecl
屬性中指定 DllImport
並不能解決問題。 不同的清理職責會導致堆疊損壞,甚至可能導致崩潰或微妙的、難以調試的錯誤,即使沒有立即發出調試器警告。 堆疊可能會被清理兩次,從而導致不可預測的行為。
解:一致的約定
關鍵是一致性。 修改 C 函數宣告以明確使用 __cdecl
:將 extern "C" int __stdcall InvokedFunction(int);
替換為 extern "C" int __cdecl InvokedFunction(int);
。 然後,確保您的 C# DllImport
屬性匹配:
<code class="language-csharp">[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]</code>
重點
仔細注意呼叫約定對於可靠的 P/Invoke 互通性至關重要。 在 C 和 C# 之間使用一致的約定可以消除堆疊不平衡並提高程式碼的整體穩健性。
以上是為什麼 __stdcall C 和 Cdecl C# 在 P/Invoke 中呼叫衝突,如何解決?的詳細內容。更多資訊請關注PHP中文網其他相關文章!