mikrocontroller.net

Forum: PC-Programmierung C++ DLL in C# verwenden - Stack-Fehler bei Parameter


Autor: Sam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe eine DLL in C++ erstellt (Visual Studio) und sie funktioniert 
auch unter C++. Das Problem zeigt sich erst, wenn ich diese in C# 
einbinden will.

Alle Funktionen ohne Parameter gehen ohne Fehler. Bei Funktionen mit 
Parameter bekomme ich immer ein Stack Problem. Auch wenn ich nur eine 
einfache Byte-Variable übergebe.

Ich glaube es liegt an meiner DLL und nicht am verwendeten Aufruf. Z.B. 
habe ich die Funktion BOOL MessageBeep(UINT) erfolgreich in C# einbinden 
können. Aber meine eigene Funktion BOOL Irgendwas(UINT) macht trotzdem 
den Stack Fehler. Ich bin etwas ratlos und hoffe auf Hilfe!

Gruß Sam

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
definiere sie mal stdcall.

Autor: Sam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin nicht sicher, ob ich Dich richtig verstanden habe. Im Moment 
sind die Funktionen mit
extern "C" __declspec(dllimport)

definiert. Stattdessen einfach
__stdcall

? Hab ich ausprobiert - es hilft leider nicht!
Das hier ist die Fehlermeldung:
Ein Aufruf an die PInvoke-Funktion 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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie hast du es in C# definiert?

Ich hatte es immer ohne __declspec(dllimport) dafür aber mit .def Datei 
gemacht. Dort hatte ich dann irgendwo __stdcall hingeschrieben und dann 
ging es. (Bei mir kam aber keine Fehlermeldung sonder das Programm ist 
nur abgestützt)

Autor: Sam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

erstmal vielen Dank für Deine Hilfe. Es funktioniert!

Ich hatte meine DLL-Funktionen bisher in etwa so definiert:
extern "C" __declspec(dllimport) BOOL Machwas(UINT u);

wenn ich nun Deinen _stdcall einbaue (an der richtigen Stelle^^), dann 
klappts!
extern "C" __declspec(dllimport) BOOL __stdcall Machwas(UINT u);

Jetzt frag ich mich nur, warum? Was macht das __stdcall? Wer mir das 
kurz erklären will, darf das gerne tun! Ansonsten werd ich das mal 
googeln.

Gruß Sam

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es legt fest wie die parameter auf den Stack gelegt werden. Bei Pascal 
ist der aufrufer für das aufräumen des Stack verantwortlich. Bei C macht 
es die funktion. Auch die Reihenfolge muss festgelegt werden und dafür 
gibt ebend verschiendene standards - einer davon ist halt stdcall

Autor: Markus Volz (valvestino)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt mehrere Möglichkeiten, wie Parameter über den Stack übergeben 
werden, wer die Daten auf den Stack legt und wer sie wieder entfernt. 
Dies definiert man über z.B. __stdcall (MS-VC). Bei MS gibt es da auch 
noch andere Calling Conventions (__cdelc, __clrcall, ...). Der Trick 
ist: die Calling-Convention muss bei Aufrufer und beim Aufgerufenen 
zusammenpassen.

Eine weitere Möglichkeit, deine Software zum Laufen zu bekommen wäre, Du 
gibst in C# beim DllImport die passende Aufruf-Konvention an.

Weiterführende Doku: siehe MSDN

Gruß
Markus

Autor: GSc_Dev (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

vielen Dank für diesen Thread!
Der Hinweis, __stdcall zu ergänzen, hat mir (nach 3 Jahren :-) sehr 
geholfen!
Grüße,
Günter

Autor: Gerald Trost (geraldtrost)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Hinweis:
Ich hatte in C# die Funktion ShowWindow() aus user32.dll eingebunden.
Alles ging problemlos bis ich die ZielPlattform auf ".NET 4.0"
geändert habe, dann kam die Stack-Fehlermeldung!
Ich kompiliere jetzt für .NET 3.5 bis ich eine Lösung gefunden habe.
Gerald

Autor: bluppdidupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht denn die Einbindung aus?
Die Variante von hier funktioniert eigentlich:
http://www.pinvoke.net/default.aspx/user32.showwindow

Autor: Gerald Trost (geraldtrost)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interessant!
Wenn man das enum ShowWindowCommands in der
Deklaration benützt dann funkt es auch unter DotNET 4.0 !

vielen Dank
Gerald

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.