Benutzer mit den meisten Antworten
Probleme mit übergeben von Parametern an Visual C++ dll

Frage
-
Hi, ich habe eine Frage, ich habe eine in Visual Studio 2010 erstellte C++ dll, ich exportiere die Funktionen folgendermaßen:
#define DLL extern "C" __declspec(dllexport) DLL int returnInt15(){ //just a test return 15; } DLL int returnInt(int zahl){ //just a test return zahl; }
In meinem C# Programm wollte ich nun testweise die 2 Funktionen probieren, mit folgendem Code:
[DllImport("HeatingDll.dll")] public static extern int returnInt15(); [DllImport("HeatingDll.dll")] public static extern int returnInt(int zahl);
Die erste Funktion funktioniert so wie sie soll, dh. wenn ich returnInt15() aufrufe, dann erhalte ich als Rückgabewert auch die gewünschten 15 :)
Wenn ich aber die zweite Funktion aufrufe, dann erhalte ich folgende Fehlermeldung:
PInvokeStackImbalance wurde erkannt.
Message: Ein Aufruf an die PInvoke-Funktion "TESTHeatDLL!TESTHeatDLL.frmMain::returnInt" hat das Gleichgewicht des Stapels gestört. Wahrscheinlich stimmt die verwaltete PInvoke-Signatur nicht mit der nicht verwalteten Zielsignatur überein. Überprüfen Sie, ob die Aufrufkonvention und die Parameter der PInvoke-Signatur mit der nicht verwalteten Zielsignatur übereinstimmen.Kann mir da bitte wer weiterhelfen?
Noch ein paar Informationen zu meinem C# Projekt: Die dll wollte ich eigentlich als Referenz zu meinem C# Projekt hinzufügen, da hat es mir aber gesagt, dass es sich nicht um eine gültige Assembly oder COM-Komponente handelt, deswegen habe ich die dll einfach zum Projekt "als vorhandenes Element" hinzugeügt, und eingestellt, dass er die dll immer ins Ausgangsverzeichnis kopieren soll.
Und noch zu C++ dll: Erstellt als win32 DLL, gemeinsam genutzt, mit /MD switch, da ich sonst fehlermeldungen beim kompilieren erhalten habe (genauen Grund kenn ich nicht, möglicherweise sogar ein MS-Bug(Feature)??)
danke und schönen Tag noch, mfg chief
Antworten
-
Hallo
> als Referenz zu meinem C# Projekt hinzufügen
dies geht nur mit Assemblies (managed Code), nicht mit native (unmanaged) DLLs.
> PInvokeStackImbalance
dies ist typisch wg der 'Aufrufkonvention' (wie in Fehlermeldung/MSDN) beschrieben.
Dies ist eine C++/Win32-Sache, siehe C++ Doku zu __stdcall und __cdecl, also kein C# Thema für hier, sondern Grundlagen!
Für DLLs mit Flat-API sollte meist das __stdcall verwendet werden, oft auch als 'WINAPI' Aufrufkonvention in Windows SDK.
Deine C Methode würde dann etwa so aussehen:
extern "C" __declspec(dllexport) int __stdcall returnInt(int zahl)
Alternativ (eher unüblich) könnte man in C# die Aufrufkonvention beim DllImport explizit auf Cdecl umstellen:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention.aspx
*** diverse Links zu DLL Grundlagen:
Exportieren aus einer DLL
http://msdn.microsoft.com/de-de/library/z4zxe9k8.aspxDeveloping DLLs
http://msdn.microsoft.com/en-us/library/bb687850.aspxCalling DLL Functions from Visual Basic Applications
http://msdn.microsoft.com/en-us/library/dt232c9t.aspx
http://msdn.microsoft.com/en-us/library/aa235591.aspx
http://support.microsoft.com/kb/841293
Die __cdecl Aufrufkonvention ist zwar default beim C/C++-Compiler,
bei DLL-Exports sollte __cdecl aber eigentlich nur für spezielle Methoden etwa mit variabler Anzahl Parameter verwendet werden.- Als Antwort vorgeschlagen Robert BreitenhoferModerator Freitag, 13. August 2010 09:25
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 17. August 2010 06:38
-
Hallo chieffun,
Habe folgendes gemacht und es war erfolgreich:
1) DLL in Visual Studio 2010 erstellt wie folgt:
// TestStringPro.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #define DLL extern "C" __declspec(dllexport) DLL int returnInt15() { return 15; } DLL int returnInt(int zahl) { return zahl; }
2) DLL in Visual Studio 2008 (C#) gerufen wie folgt:
using System; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [DllImport("C:\\Temp\\TestStringPro.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int returnInt(int myint); [DllImport("C:\\Temp\\TestStringPro.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int returnInt15(); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { textBox1.Text = returnInt(1234567890).ToString(); textBox2.Text = returnInt15().ToString(); } } }
Grüße,
Robert
- Als Antwort markiert chieffun Dienstag, 17. August 2010 06:29
Alle Antworten
-
Hallo
> als Referenz zu meinem C# Projekt hinzufügen
dies geht nur mit Assemblies (managed Code), nicht mit native (unmanaged) DLLs.
> PInvokeStackImbalance
dies ist typisch wg der 'Aufrufkonvention' (wie in Fehlermeldung/MSDN) beschrieben.
Dies ist eine C++/Win32-Sache, siehe C++ Doku zu __stdcall und __cdecl, also kein C# Thema für hier, sondern Grundlagen!
Für DLLs mit Flat-API sollte meist das __stdcall verwendet werden, oft auch als 'WINAPI' Aufrufkonvention in Windows SDK.
Deine C Methode würde dann etwa so aussehen:
extern "C" __declspec(dllexport) int __stdcall returnInt(int zahl)
Alternativ (eher unüblich) könnte man in C# die Aufrufkonvention beim DllImport explizit auf Cdecl umstellen:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention.aspx
*** diverse Links zu DLL Grundlagen:
Exportieren aus einer DLL
http://msdn.microsoft.com/de-de/library/z4zxe9k8.aspxDeveloping DLLs
http://msdn.microsoft.com/en-us/library/bb687850.aspxCalling DLL Functions from Visual Basic Applications
http://msdn.microsoft.com/en-us/library/dt232c9t.aspx
http://msdn.microsoft.com/en-us/library/aa235591.aspx
http://support.microsoft.com/kb/841293
Die __cdecl Aufrufkonvention ist zwar default beim C/C++-Compiler,
bei DLL-Exports sollte __cdecl aber eigentlich nur für spezielle Methoden etwa mit variabler Anzahl Parameter verwendet werden.- Als Antwort vorgeschlagen Robert BreitenhoferModerator Freitag, 13. August 2010 09:25
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 17. August 2010 06:38
-
Und noch zu C++ dll: Erstellt als win32 DLL, gemeinsam genutzt, mit /MD switch, da ich sonst fehlermeldungen beim kompilieren erhalten habe (genauen Grund kenn ich nicht, möglicherweise sogar ein MS-Bug(Feature)??)
definitiv ein reines Visual C++ Thema,
http://msdn.microsoft.com/de-de/library/2kzt1wy3.aspx
http://msdn.microsoft.com/de-de/library/abx4dbyh.aspx
achte insbesondere auf die Abhängigkeit deiner DLL von der C-Runtime (welche ggf die VC-Redist im Setup [beim Kunden] benötigt). -
Hallo chieffun,
Habe folgendes gemacht und es war erfolgreich:
1) DLL in Visual Studio 2010 erstellt wie folgt:
// TestStringPro.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #define DLL extern "C" __declspec(dllexport) DLL int returnInt15() { return 15; } DLL int returnInt(int zahl) { return zahl; }
2) DLL in Visual Studio 2008 (C#) gerufen wie folgt:
using System; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [DllImport("C:\\Temp\\TestStringPro.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int returnInt(int myint); [DllImport("C:\\Temp\\TestStringPro.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int returnInt15(); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { textBox1.Text = returnInt(1234567890).ToString(); textBox2.Text = returnInt15().ToString(); } } }
Grüße,
Robert
- Als Antwort markiert chieffun Dienstag, 17. August 2010 06:29