Dépannage des incompatibilités de convention d'appel C# P/Invoke
Cet article explique un problème courant lors de l'utilisation de Platform Invoke (P/Invoke) pour interagir entre le code C# et C. Nous nous concentrerons sur la question des conventions d'appel incompatibles : CallingConvention.Cdecl
en C# versus __stdcall
en C .
Conventions d'appel expliquées
Dans les environnements 32 bits, les conventions d'appel dictent la transmission des paramètres, le stockage de la pile et le nettoyage. Les conventions clés incluent :
__stdcall
: L'appelant pousse des arguments ; l'appelé nettoie la pile. Utilisé par les API Windows et COM.__cdecl
: L'appelant pousse les arguments et nettoie la pile. Norme pour C.__fastcall
: Utilise des registres pour certains arguments, améliorant potentiellement la vitesse mais réduisant la compatibilité.__thiscall
: Similaire à __cdecl
, mais gère le pointeur "this" dans les fonctions membres C.__clrcall
: Une convention d'appel gérée équilibrant les éléments des autres, évitant ainsi les problèmes de pile.Analyse d'exemples de code
Considérons une fonction C :
<code class="language-c++">extern "C" int __stdcall InvokedFunction(int);</code>
Et son homologue 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>
Le choc des conventions
Le problème vient du CallingConvention.Cdecl
en C# en conflit avec le __stdcall
en C . Cela conduit à des déséquilibres de pile. Bien que __stdcall
soit souvent la valeur par défaut de P/Invoke (en raison de la prévalence de l'API Windows), l'interface avec le code __cdecl
C nécessite une spécification de convention explicite.
Résolution
La solution est simple : alignez la convention d'appel C# avec celle du 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>
Clé à retenir
Comprendre les conventions d'appel est essentiel pour une interopérabilité multilingue réussie. Les conventions de correspondance évitent les erreurs de pile et garantissent une intégration fluide en C# et C.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!