Hallo,
ich bin gerade dabei eine .NET-Komponente zu entwickeln die einen in Delphi-
Win32 geschriebenen Parser benutzt. Dafür implementieren diverse Klassen im Parser Interfaces die dann auch unter .NET angesprochen werden können, wodurch ich quasi in .NET mit den Delphi-Objekten des Parsers arbeiten kann. Soweit so gut, inzwischen funktioniert das auch recht gut. Mir ist dabei allerdings eine Sache aufgefallen - wenn ich von .NET aus eine Funktion aufrufe (also Code von dem ein Rückgabewert erwartet wird), so endet das immer in einer
Exception (egal ob es sich dabei um eine Interface-Methode oder eine normale Funktion die mittels DllImport importiert wurde handelt).
Ich bin der Sache auf den Grund gegangen und bin dabei zu folgendem Ergebnis gekommen:
Alle Funktionen und Methoden sind als stdcall deklariert, folglich werden die Parameter von rechts nach links auf dem Stack übergeben. Bei einer Funktion wie dieser
function Parse(const s: WideString): IParsedObject; stdcall
wäre das also:
- Zeiger auf String (s)
- Zeiger auf Objekt (Self - da es eine Methode eines Interface ist)
Für den Rückgabewert schiebt Delphi erst NACH allen anderen Parametern eine Adresse auf den Stack, wo das Ergebnis abgelegt werden soll. Bei einem Aufruf würde der Stack also so aussehen:
Wenn ich statt der Funktion eine Prozedur mit out-Parameter mache
procedure Parse2(const s: WideString; out Result: IParsedObject); stdcall;
ergibt sich bei einem Aufruf folgender Stack:
Man beachte den Unterschied in der Reihenfolge zur Funktion!
Wenn ich nun von .NET aus die Prozedur "Parse2" (also die Prozedur mit out-Parameter) aufrufe, so funktioniert alles wunderbar, die Parameter werden also in der richtigen Reihenfolge übergeben. Rufe ich jedoch die Funktion "Parse" auf kracht es, denn .NET übergibt die Parameter in derselben Reihenfolge wie bei "Parse2", wodurch natürlich alles durcheinander kommt.
Die Frage ist jetzt: wer machts richtig - Delphi oder .NET?
Wenn ich in Delphi die Methode so umdeklariere, dass sie statt statt eines IParsedObject-Interface einen einfachen Pointer zurückliefert funktioniert es lustigerweise wieder - Delphi ändert in diesem Fall also die Reihenfolge der Parameter am Stack. Aus diesem Grund liegt für mich die Vermutung nahe, dass Delphi hier *mist* baut.
Dasselbe Problem gibt es übrigens auch bei Funktionen die WideStrings zurückliefern.
Hat jemand dieses Verhalten auch schon einmal beobachten können und gibt es eine Lösung dafür? Ich will eigentlich ungern nur Prozeduren mit out-Parametern verwenden...
Gruß, Motzi