AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein DLL mit Strings von D10 nach Delphi 6
Thema durchsuchen
Ansicht
Themen-Optionen

DLL mit Strings von D10 nach Delphi 6

Ein Thema von kmma · begonnen am 25. Okt 2023 · letzter Beitrag vom 27. Okt 2023
Antwort Antwort
Seite 1 von 2  1 2      
kmma

Registriert seit: 26. Jul 2010
16 Beiträge
 
Delphi 2 Desktop
 
#1

DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 16:29
Ich habe eine DLL in Delphi 10 die eien String zurückgeben soll. Das ganze soll (muss) in einer D6 Anwendung geladen wewrden.
sharemem ist als erstes in den uses eingebunden, der String ist als ansistring definiert.

Der String wird zwar in D6 richtig angezeigt, beim Beenden der Funktion kommt es aber zu einem Speicherzugriffsfehler.
Was ist da noch zu beachten?

In Delphi 10:
function ExportString: ansistring; export;
begin
result := 'Hallo'
end;

In D6:

procedure TForm1.Button1Click(Sender: TObject);
type TStringFunction = function: ansistring;
var StringFunction: TStringFunction;
h: hmodule;
p: pointer;
begin
h := LoadLibrary(pchar('s:\D\Delphi\Test.dll'));
if h <> 0 then
begin

p := GetProcAddress(h, 'ExportString');
form1.tag := integer(p);
@StringFunction := p;
form1.caption := StringFunction; // Klappt noch

end;
end; // hier kracht es
  Mit Zitat antworten Zitat
Benutzerbild von dummzeuch
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
1.623 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 16:46
Ich bin mir ziemlich sicher, dass Sharemem von Delphi 10 und Sharemem von Delphi 6 nicht kompatibel sind. Deshalb müsstest Du auf PAnsiChar oder WideString umstellen.
Thomas Mueller
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.202 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 17:26
Ich habe eine DLL in Delphi 10 die eien String zurückgeben soll. Das ganze soll (muss) in einer D6 Anwendung geladen wewrden.
sharemem ist als erstes in den uses eingebunden, der String ist als ansistring definiert.

Der String wird zwar in D6 richtig angezeigt, beim Beenden der Funktion kommt es aber zu einem Speicherzugriffsfehler.
Was ist da noch zu beachten?
3 Möglichkeiten:
a, Entweder baust du eine C-Kompatible Schnittstelle. Also kein AnsiString sondern P(Ansi)Char und Co
b, Exe und DLL sind mit der gleichen Delphi-Version erstellt
c, Du nutzt WideString, so das hier die Speicherverwaltung von Windows genutzt wird und kein Probleme mit
2 Speichermanagern in D6 und D100 auftauchen
Das gibt es auch unter D6, da sonst kein COM genutzt werden könnte.

Ich würde die auch empfehlen komplett von D6 weg zu kommen.
Die Produktivität von D10(.4 bei uns) ist sehr viel höher als mit D6.
Ich würde keinen Job mehr mit D6 anfangen wollen (außer die erste Aufgabe wäre Update auf aktuelles Delphi)
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 18:22
Strings wurden im Jahre 2009 intern umgebaut. Aktuelle "LongStrings" haben zwei Felder mehr. (der Offset zwischen String-Zeiger und Speicher-Block hat sich verschoben)
Außerdem mußt du mit der Speicherverwaltung aufpassen -> Shared Memory.

Hier ein paar Threads, unter Anderem auch diesbezüglich,
wo ich zuletzt auch damit gekämpft hatte, zwischen Delphi 7 und 11.3.
https://www.delphipraxis.net/213732-...n-gesucht.html
https://www.delphipraxis.net/213691-...-methoden.html
https://www.delphipraxis.net/213736-...-fuer-neu.html

Fazit: Nimm WideString, ShortString, PChar PAnsiChar/PWideChar oder andere CharArrays.
Ebenso ginge OleVariant .... nicht Variant, da Letzteres ebenfalls die LongStrings enthält, wobei vor 2009 das Delphi den UnicodeString nicht kennt.

WideString kapselt den BSTR (OLE-String), also dessen WinAPI der OleAut32.dll, aka MSDN-Library durchsuchenSysAllocString usw.
$2B or not $2B

Geändert von himitsu (25. Okt 2023 um 18:28 Uhr)
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.960 Beiträge
 
Delphi 12 Athens
 
#5

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 18:41
Außer der Empfehlung auch von meiner Seite von D6 weg zu kommen noch der hinweis,
dass man sicherheitshalber auch eine Calling Convention bei der Deklaration der Funktion
in der DLL und im aufrufenden Programm angeben sollte. z. B. StdCall.
Nich dass da mal wer unbedacht dran schraubt...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 18:47
Oder explizit "register" als Calling-Convention hinschreiben.

Nein, "pascal" ist nicht das, was Delphi standardmäßig benutzt, auch wenn es danach klingen mag.
https://docwiki.embarcadero.com/RADS...l_und_safecall



Und unter Win64 ist es eh egal, da es dort nur noch eine Convention gibt
und sämtliche Compiler alle Angaben einer Convention ignorieren.
$2B or not $2B
  Mit Zitat antworten Zitat
kmma

Registriert seit: 26. Jul 2010
16 Beiträge
 
Delphi 2 Desktop
 
#7

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 20:48
Danke erstmal für die Antworten. Das Problem ist, dass ich an der D6 Seite nichts machen kann, die Anwendung ist da und soll so bleiben (außerhalb meines Einflußbereiches).
Natürlich könnte ich die DLL in D6 erstellen, aber zum einen will ich ja hin zu D10, außerdem gibt es da ein paar sehr nette Funktionen in D10, die ich für diese Aufgabe gut gebrauchen kann.

Ich habe jetzt ein wenig experimentiert und eine "Lösung" gefunden, die zumindest in der kleinen Testumgebeung funktioniert. Jetzt würde ich gerne wissen, ob das Zufall ist und bei anderen Konstllation auch zu Abstürzen führt oder ob das zwar prinzipiell sehr unsauber programmiert ist, aber der Zweck heiligt die Mittel.

Also wie gesagt an der D6 Seite kann/will/darf ich nicht ändern.
Da gibt es einfach die Funktion (vereinfacht)
Code:
 
type TStringFunction = function: string;
Ich habe jetzt die D10 Funktion so umgebaut dass ich quasi einen Widestring als Container für einen Ansistring missbrauche. Je nach Länge des zu übergebenden Strings wird eben am Ende ein #0 mit übermttelt, aber das wäre in der D6 Anwendug kein Problem.
Code:
function ExportString: widestring; Export;
  var Ansi: ansistring;
begin
  ansi := 'Hallo';
  setlength(result, (length(ansi) div 2) + (length(ansi) mod 2));
  fillchar(result[1], 2 * length(result), 0);
  move(ansi[1], result[1], length(ansi));
//  result := 'hallo';
end;
Jedenfalls kommt in der D6 Anwendung ein "Hallo" +#0 an. Die Frage ist jetzt eben, ob ich da nur zufälligerweise keine Speicherverletzung erlebe oder ob das prinzipiell so gehen kann.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 20:53
Wenn da mit Strings über DLL-Grenzen hinaus agiert wird, kannst du das sauber nicht mit neuen Delphiversionen kombinieren.

Die einzig saubere Lösung:
Entwirf eine saubere neue DLL-Schnittstelle auf dem neuen Stand, sei es mit WideString oder P(Wide/Ansi)Char. Dann schreibe in Delphi 6 eine Wrapper-DLL, die nach außen die alte Funktionalität mit Sharemem bietet.

Auf diese Weise hast du dann für die Zukunft eine moderne DLL ohne Tricksereien, die trotzdem sauber in das alte System integriert werden kann.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#9

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 21:31
Siehe mein gezeigtes Projekt.
Von D7 zu 2009+ und umgekehrt.
Der originale D7-Code konnte nicht geändert werden.
Drum wurde eine D7-DLL erstellt (es gab noch Keine, nur die DCUs ... aber darum konnte ich drüben auch bissl was einfügen, um diesen Teil nicht auf Seite des 2009+ machen zu müssen ... aber im Grunde egal, wer von Beiden es macht)

Das alte Delphi kann LongStrings AnsiStrings/UTF8String/usw., des neuen Delphi lesen.
Es kann für sich selber auch Kopien erstellen, via Referenzzählung oder komplett.
Es darf aber niemals einen fremden String, des neuen Delphi, verändern oder freigeben.

Das neue Delphi kann/darf dagegen KEINEN AnsiStrings des alten Delphis lesen/bearbeiten/freigeben ... absolut nichts, da die neuen Felder nicht existieren und der Zugriff darauf fehlschlagen muß.

Darum hatte ich mir auch die Funktion zum Bearbeiten ins andere Delphi rübergezogen, denn es nutzt dadurch die Funktionen und den Speichermanager der anderen Seite.

Außnahme, was Beide können: Egal ob als AnsiString oder PAnsiChar übergeben wurde, es kann immer als über einen Cast nach PAnsiChar gelesen werden.
(auch Ändern einzelner Chars, über den PAnsiChar, also nur, wenn dabei nichts in der Speicherverwaltung angestoßen wird)
$2B or not $2B

Geändert von himitsu (25. Okt 2023 um 23:35 Uhr)
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
353 Beiträge
 
#10

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 26. Okt 2023, 09:19
Hi,

Is this acceptable to be solved by a hack ?

As i think it is doable but with little hacking around, see the the string structure is different, but we can utilize the fact of how Delphi handle constant (literal) strings, if the reference count is -1 ($FFFFFFFF) then it will always copy it, so in theory which i see doable, you have to overwrite and adjust your returned string to have the same structure as Delphi 6.
so the steps should be like:

1) in Delphi 10 and when the result is ready to returned, a copy of the pointer is stored in a garbage collecting list, this is crucial because we need to fix it later and release the memory preventing leak and corruption in the DLL.
2) rewrite the structure to be compatible with Delphi 6, means overwrite the 16bit "codePage" and "elemSize" as one cardinal 32bit, with value $FFFFFFFF (-1), and put the length in refCount.
3) now Delphi 6 should copy all the returned strings to its own allocated strings, as it will see them as constants.
4) we need an entry point to clean the garbage, it could be the first line in every call to DLL in Delphi 10, to restore the string refcount and assign it to an empty string ''.

This is working in my head and before writing code to demonstrate it and waste time, i would know if this is acceptable, also i don't have now an access to Delphi 6 or 7 to test it with a debugger.

On side note : i saw somewhere that himitsu has a unique love/hate for garbage collectors in Delphi, and i would love to hear your opinions.
Kas
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 14:55 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