Fehlerbehebung bei Nichtübereinstimmungen der C# P/Invoke Calling Convention
In diesem Artikel wird ein häufiges Problem bei der Verwendung von Platform Invoke (P/Invoke) zur Interaktion zwischen C#- und C-Code erläutert. Wir konzentrieren uns auf das Problem nicht übereinstimmender Aufrufkonventionen: CallingConvention.Cdecl
in C# versus __stdcall
in C.
Anrufkonventionen erklärt
In 32-Bit-Umgebungen bestimmen Aufrufkonventionen die Parameterübergabe, Stapelspeicherung und Bereinigung. Zu den wichtigsten Konventionen gehören:
__stdcall
: Der Anrufer bringt Argumente vor; Der Angerufene bereinigt den Stapel. Wird von Windows-APIs und COM verwendet.__cdecl
: Der Aufrufer schiebt Argumente und bereinigt den Stapel. Standard für C.__fastcall
: Verwendet Register für einige Argumente, was möglicherweise die Geschwindigkeit verbessert, aber die Kompatibilität verringert.__thiscall
: Ähnlich wie __cdecl
, verarbeitet aber den „this“-Zeiger in C-Memberfunktionen.__clrcall
: Eine verwaltete Aufrufkonvention, die Elemente von anderen ausgleicht und Stapelprobleme verhindert.Code-Beispielanalyse
Stellen Sie sich eine C-Funktion vor:
<code class="language-c++">extern "C" int __stdcall InvokedFunction(int);</code>
Und sein C# P/Invoke-Gegenstück:
<code class="language-csharp">[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)] private static extern int InvokedFunction(IntPtr intArg);</code>
The Convention Clash
Das Problem ergibt sich daraus, dass CallingConvention.Cdecl
in C# mit dem __stdcall
in C in Konflikt steht. Dies führt zu Stapelungleichgewichten. Während __stdcall
häufig der P/Invoke-Standardwert ist (aufgrund seiner Windows-API-Prävalenz), erfordert die Schnittstelle mit __cdecl
C-Code eine explizite Konventionsspezifikation.
Auflösung
Die Lösung ist einfach: Richten Sie die C#-Aufrufkonvention an der C-Konvention aus:
<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>
Schlüssel zum Mitnehmen
Das Verständnis von Aufrufkonventionen ist für eine erfolgreiche sprachübergreifende Interoperabilität von entscheidender Bedeutung. Passende Konventionen verhindern Stapelfehler und sorgen für eine reibungslose C#- und C-Integration.
Das obige ist der detaillierte Inhalt vonWarum schlägt mein C#-P/Invoke-Aufruf mit „CallingConvention.Cdecl' fehl, wenn eine C-Funktion „__stdcall' aufgerufen wird?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!