Un appel à la fonction PInvoke ” a déséquilibré la stack

Je reçois cette erreur bizarre sur certains trucs que j’utilise depuis longtemps. C’est peut-être une nouveauté dans Visual Studio 2010 mais je n’en suis pas certain.
J’essaie d’appeler une fonction non écrite écrite en C ++ à partir de C #.
D’après ce que j’ai lu sur Internet et le message d’erreur lui-même, cela a quelque chose à voir avec le fait que la signature de mon fichier C # n’est pas la même que celle de C ++, mais je ne la vois pas vraiment.
Tout d’abord, c’est ma fonction ci-dessous:

TEngine GCreateEngine(int width,int height,int depth,int deviceType); 

Et voici ma fonction en C #:

 [DllImport("Engine.dll", EntryPoint = "GCreateEngine", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr CreateEngine(int width,int height,int depth,int device); 

Quand je débogue en C ++, je vois tous les arguments très bien, donc je ne peux que penser que cela a quelque chose à voir avec la transformation de TEngine (qui est un pointeur vers une classe nommée CEngine) en IntPtr. Je l’ai déjà utilisé dans VS2008 sans aucun problème.

Le problème réside peut-être dans la convention d’appel. Êtes-vous sûr que la fonction non gérée a été compilée en tant que stdcall et pas autre chose (je suppose que fastcall)?

J’avais un fichier dll _cdecl c ++ que j’ai appelé sans problème avec Visual Studio 2008, puis le code identique dans Visual Studio 2010 ne fonctionnait pas. J’ai eu le même PInvoke … a également déséquilibré l’erreur de stack.

La solution pour moi était de spécifier la convention d’appel dans l’atsortingbut DllImport (…): De:

 [DllImport(CudaLibDir)] 

À:

 [DllImport(CudaLibDir, CallingConvention = CallingConvention.Cdecl)] 

Je suppose qu’ils ont changé la convention d’appel par défaut pour DLLImport entre .NET 3.5 et .NET 4.0?

Il se peut également que dans le .NET Framework version 3.5, le MDA pInvokeStackImbalance soit désactivé par défaut. Sous 4.0 (ou peut-être VS2010), il est activé par défaut .

Oui. Techniquement, le code était toujours erroné et les versions précédentes du framework le corrigeaient en silence.

Pour citer le document Problèmes de migration de .NET Framework 4 : “Pour améliorer les performances d’interopérabilité avec le code non géré, les conventions d’appel incorrectes dans un appel de plate-forme entraînent l’échec de l’application. Dans les versions précédentes, la couche marshaling résolvait ces erreurs. Si vous disposez de fichiers binarys ne pouvant pas être mis à jour, vous pouvez inclure l’élément < NetFx40_PInvokeStackResilience > dans le fichier de configuration de votre application pour résoudre les erreurs d’appel comme dans les versions précédentes.

Un moyen simple de résoudre ce problème est de spécifier la convention d’appel et de vous assurer qu’elle est la même que dans la DLL. Un __declspec(dllexport) devrait donner un format cdecl .

 [DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl)] 

Utilisez le code suivant, si par exemple votre DLL porte le nom MyDLL.dll et que vous souhaitez utiliser la fonction MyFunction dans la DLL

 [DllImport("MyDLL.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] public static extern void MyFunction(); 

Cela a fonctionné pour moi.

Dans mon cas (VB 2010 et DLL compilé avec Intel Fortran 2011 XE), le problème existe lorsque mon application cible .NET Framework 4. Si je modifie une infrastructure ciblée vers la version 3.5, tout fonctionne correctement comme prévu. Donc, je suppose que la raison est quelque chose introduit dans .Net Framework 4 mais je ne sais pas pour le moment lequel

Mise à jour: le problème a été résolu en recompilant Fortran DLL et en spécifiant explicitement STDCALL comme convention d’appel pour les noms d’exportation dans la DLL.