Ein Aufruf der PInvoke-function ” hat den Stack unausgeglichen

Ich bekomme diesen seltsamen Fehler bei einigen Sachen, die ich seit einiger Zeit benutze. Es kann eine neue Sache in Visual Studio 2010 sein, aber ich bin mir nicht sicher.
Ich versuche eine von C # in C ++ geschriebene nicht erweiterte function aufzurufen.
Von dem, was ich im Internet gelesen habe und der Fehlermeldung selbst hat es etwas mit der Tatsache zu tun, dass die Signatur in meiner C # -Datei nicht die gleiche wie die von C ++ ist, aber ich kann es wirklich nicht sehen.
Zuallererst ist das meine unangegangene function unten:

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

Und hier ist meine function in C #:

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

Wenn ich in C ++ debugge, sehe ich alle Argumente gut, also kann ich nur denken, dass es etwas mit der Umwandlung von TEngine (das ist ein pointers auf eine class namens CEngine) zu IntPtr zu tun hat. Ich habe das vorher in VS2008 ohne Probleme benutzt.

    Vielleicht liegt das Problem in der Aufrufkonvention. Sind Sie sicher, dass die nicht verwaltete function als stdcall kompiliert wurde und nicht etwas anderes (ich würde fastcall erraten)?

    Ich hatte eine _cdecl C ++ DLL, die ich ohne Probleme von Visual Studio 2008 anrief, und dann würde der identische Code in Visual Studio 2010 nicht funktionieren. Ich habe die gleiche PInvoke … hat auch den Stapelerrors aus dem Gleichgewicht gebracht.

    Die Lösung für mich war, die Aufrufkonvention im Attribut DllImport (…) anzugeben: Von:

     [DllImport(CudaLibDir)] 

    Zu:

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

    Ich denke, sie haben die Standard-Aufrufkonvention für DLLImport zwischen .NET 3.5 und .NET 4.0 geändert?

    Es könnte auch sein, dass der PInvokeStackImbalance-MDA in der .NET Framework-Version 3.5 standardmäßig deaktiviert ist. Unter 4.0 (oder vielleicht VS2010) ist es standardmäßig aktiviert .

    Ja. Technisch gesehen war der Code immer falsch und frühere Versionen des Frameworks bereinigten ihn stillschweigend.

    Um das .NET Framework 4 Migration Issues-Dokument zu zitieren: “Um die performance bei der Interoperabilität mit nicht verwaltetem Code zu verbessern, führen jetzt falsche Aufrufkonventionen in einem Plattformaufruf dazu, dass die Anwendung fehlschlägt. In früheren Versionen hat die Marshalling-Schicht diese Fehler im Stack behoben.” Wenn Sie Binärdateien haben, die nicht aktualisiert werden können, können Sie das < NetFx40_PInvokeStackResilience > -Element in die Konfigurationsdatei Ihrer Anwendung aufnehmen, um zu ermöglichen, dass aufrufende Fehler wie bei früheren Versionen im Stapel aufgetriggers werden. Dies kann jedoch die performance Ihrer Anwendung beeinträchtigen.

    Eine einfache Möglichkeit, dies zu beheben, besteht darin, die Aufrufkonvention anzugeben und sicherzustellen, dass sie identisch mit der DLL ist. Ein __declspec(dllexport) sollte ein Cdecl- Format ergeben.

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

    Verwenden Sie den folgenden Code, wenn Ihre DLL beispielsweise den Namen MyDLL.dll hat und Sie die function MyFunction innerhalb der DLL verwenden möchten

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

    Das hat für mich funktioniert.

    In meinem Fall (VB 2010 und DLL kompiliert mit Intel Fortran 2011 XE) existiert das Problem, wenn meine Anwendung .NET Framework 4 als Ziel hat. Wenn ich das Zielframework auf Version 3.5 ändere, dann funktioniert alles wie erwartet. Also, ich denke der Grund ist etwas, das in .Net Framework 4 eingeführt wurde, aber ich habe im Moment keine Ahnung welches

    Update: Das Problem wurde behoben, indem die Fortran-DLL neu kompiliert wurde und STDCALL explizit als Aufrufkonvention für Exportnamen in der DLL angegeben wurde.