AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Delphi-Bug bei stdcall-Convention?

Ein Thema von Motzi · begonnen am 17. Apr 2007 · letzter Beitrag vom 18. Apr 2007
Antwort Antwort
Benutzerbild von Motzi
Motzi

Registriert seit: 6. Aug 2002
Ort: Wien
598 Beiträge
 
Delphi XE2 Professional
 
#1

Delphi-Bug bei stdcall-Convention?

  Alt 17. Apr 2007, 16:13
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:
  • s
  • Self
  • Result

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:
  • Result
  • s
  • Self

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
Manuel Pöter
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#2

Re: Delphi-Bug bei stdcall-Convention?

  Alt 18. Apr 2007, 12:43
Zitat von Motzi:
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.
Hi,
das wäre schon an dieser Stelle imho kein stdcall mehr, wenn Delphi eine Adresse auf den Stack schiebt, wo etwas gespeichert werden soll. Ergebnisse werden per Definition immer über das EAX Register zurückgegeben.

An sich muss ich aber sagen, dass ich mir weder vorstellen kann, dass Delphi noch .net hier wirklich schuld sind. Bei Delphi spricht eindeutig dagegen, dass diese Aufrufkonvention ja auch für alle Windows-DLL-Aufrufe verwendet wird (also nicht alle DLLs unter Windows, aber die von MS für Windows).
Bei .net wiederum kann ich mir nicht vorstellen, dass ausgerechnet die hausintern bevorzugte Aufrufkonvention nicht funktionieren sollte! Auch die MS Leute werden sicherlich ihre Funktionen testen. Und wenn hier ein Fehler vorliegen würde, der wäre doch mit Sicherheit schon bekannt.
Bleibt noch die Möglichkeit, dass irgendeine von Dir gewählte Kombination aus Einstellungen und Source dazu führt (muss ja nicht zwangsweise ein Programmierfehler sein), was ich persönlich für wahrscheinlicher halten würde (nicht böse gemeint)

Gruß Der Unwissende
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Delphi-Bug bei stdcall-Convention?

  Alt 18. Apr 2007, 12:57
ich würde es einfach mal auf den WideString schieben. Ich glaub der wird ebenfalls von dem Abschnitt ganz oben in der DLL angesprochen. (den ShareMem-Kommentarteil)
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von Motzi
Motzi

Registriert seit: 6. Aug 2002
Ort: Wien
598 Beiträge
 
Delphi XE2 Professional
 
#4

Re: Delphi-Bug bei stdcall-Convention?

  Alt 18. Apr 2007, 13:35
Nein, am WideString kann es nicht liegen. WideStrings entsprechen dem BSTR Datentyp von COM (der Speicher dafür wird auch über SysAllocString reserviert und nicht über den Delphi-internen MemoryManager) und können problemlos vom Marshaler verarbeitet werden. Wenn ich den Rückgabewert der Funktion von WideString auf PWideChar ändere funktioniert es. Das Problem liegt anscheinend wirklich daran, dass Delphi bei unterschiedlichen Typen die Parameter in unterschiedlicher Reihenfolge auf den Stack legt - und das bei gleicher Aufrufkonvention.

Das ist meiner Meinung nach ein Bug! Das Problem tritt übrigens unter Delphi 2006 Prof auf. Ich werd mal probieren ob es unter meinem Delphi 6 auch auftritt...

Gruß, Motzi

edit: grad getestet - unter Delphi 6 verhält es sich ganz genauso.
Manuel Pöter
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz