Hey
Je reçois cette erreur bizarre sur certains trucs que j'utilise depuis un certain temps. Il s'agit peut-être d'une nouveauté de Visual Studio 2010, mais je n'en suis pas sûr.
J'essaie d'appeler une fonction inchangée écrite en C++ depuis 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 du C++, mais je ne vois vraiment pas pourquoi.
Tout d'abord, voici ma fonction inchangée 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);
Lorsque je débogue en C++, je vois tous les arguments sans problème. Je ne peux donc que penser que cela a quelque chose à voir avec la transformation de TEngine (qui est un pointeur vers une classe appelée CEngine) en IntPtr. J'ai déjà utilisé cette méthode dans VS2008 sans problème.
J'espère que mon problème est suffisamment clair pour que vous puissiez le comprendre.
Réponses
Trop de publicités?J'avais une dll c++ _cdecl que j'ai appelée sans problème depuis Visual Studio 2008, puis le code identique dans Visual Studio 2010 ne fonctionnait pas. J'ai obtenu la même erreur PInvoke ... a déséquilibré la pile également.
La solution pour moi a été de spécifier la convention d'appel dans l'attribut DllImport(...) : De : [DllImport(CudaLibDir)] Vers : [DllImport(CudaLibDir, CallingConvention = CallingConvention.Cdecl)]
Je suppose qu'ils ont changé la convention d'appel par défaut pour DLLImport entre .Net3.5 et .Net4.0.
Il se peut également que dans la version 3.5 de .NET Framework, le MDA pInvokeStackImbalance soit désactivé par défaut. Sous la version 4.0 (ou peut-être VS2010), elle est activé par défaut .
Oui. Techniquement, le code a toujours été faux, et les versions précédentes du le framework l'a corrigé silencieusement.
Pour citer le Document sur les problèmes de migration de .NET Framework 4 : "Pour améliorer performance dans l'interopérabilité avec le code non géré, les conventions d'appel d'appel incorrectes dans un invoke de plate-forme provoquent maintenant l'échec de l'application. Dans versions précédentes, la couche de marshaling résolvait ces erreurs en haut de la pile... Si vous avez des binaires qui ne peuvent pas être mis à jour, vous pouvez inclure le fichier < NetFx40_PInvokeStackResilience > dans le fichier de configuration de votre application afin d'activer l'appel des d'être résolues en haut de la pile comme dans les versions précédentes. Cependant, cela peut affecter les performances de votre application."
Une façon simple de résoudre ce problème est de spécifier la convention d'appel et de s'assurer qu'elle est la même que dans la DLL. A __declspec(dllexport)
devrait donner un cdecl format.
[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl)]
Dans mon cas (VB 2010 et DLL compilé avec Intel Fortran 2011 XE), le problème se pose lorsque mon application cible .NET Framework 4. Si je change le framework ciblé pour la version 3.5, alors tout fonctionne bien comme prévu. Donc, je suppose que la raison est quelque chose d'introduit dans .Net Framework 4 mais je n'ai aucune idée pour le moment de laquelle
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.