Maison > développement back-end > C++ > Pourquoi mon appel C# P/Invoke avec « CallingConvention.Cdecl » échoue-t-il lors de l'appel d'une fonction C « __stdcall » ?

Pourquoi mon appel C# P/Invoke avec « CallingConvention.Cdecl » échoue-t-il lors de l'appel d'une fonction C « __stdcall » ?

Patricia Arquette
Libérer: 2025-01-25 23:51:11
original
410 Les gens l'ont consulté

Why Does My C# P/Invoke Call With `CallingConvention.Cdecl` Fail When Calling a C   `__stdcall` Function?

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>
Copier après la connexion

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>
Copier après la connexion

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>
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal