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
478 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 :

extern "C" int __stdcall InvokedFunction(int);
Copier après la connexion

Et son homologue C# P/Invoke :

[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
private static extern int InvokedFunction(IntPtr intArg);
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 :

[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Stdcall)]
private static extern int InvokedFunction(int intArg); // Note: IntPtr changed to int
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!

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