AGB  ·  Datenschutz  ·  Impressum  







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

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
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.960 Beiträge
 
Delphi 12 Athens
 
#1

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 19: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.373 Beiträge
 
Delphi 12 Athens
 
#2

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 25. Okt 2023, 20: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)
Ein Therapeut entspricht 1024 Gigapeut.

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

Registriert seit: 3. Sep 2023
412 Beiträge
 
#3

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 26. Okt 2023, 08: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
Kas Ob.

Registriert seit: 3. Sep 2023
412 Beiträge
 
#4

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 26. Okt 2023, 08:28
Thinking more

We don't need a string, just a copy of the string in the memory adjusted to look like a string and let the DLL clear its string nicely and orderly meaning return the pointer with 8 bytes increase, as long the return fake string have refcount = -1 the application will copy its content as string from constant with the right length, this will simplify the Garbage collector from restoring the string then force to clear, or to have to save original refcount and restore it.
Kas
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
412 Beiträge
 
#5

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 27. Okt 2023, 11:12
@kmma ,

Have you tested the proposed constant hack ?

Please try this
Code:
// these for single thread
function BuiltOldAnsiString(const aString: AnsiString): Pointer; overload;
function BuiltOldAnsiString(const aString: string): Pointer; overload;

// these for multi thread application
// these might leave one memory leak per thread as worse case, just one leak that can be registered
function BuiltOldAnsiStringMt(const aString: AnsiString): Pointer; overload;
function BuiltOldAnsiStringMt(const aString: string): Pointer; overload;

implementation
var
  gTempBufferForEmulatedOldAnsi: array of byte;

threadvar
  gTempBufferForEmulatedOldAnsiThreadSafe: array of byte;

function BuiltOldAnsiString(const aString: AnsiString): Pointer; overload;
var
  Len: Integer;
  Mem: PCardinal;
begin
  Len := Length(aString);
  if Len = 0 then
  begin
    Result := nil;
    Exit;
  end;

  SetLength(gTempBufferForEmulatedOldAnsi, Len + 8 + 1); // header + 1 null ansi char
  Mem := @gTempBufferForEmulatedOldAnsi[0];
  Mem^ := $FFFFFFFF;           // refcount =(-1) emulating constant string
  Inc(Mem, 1);
  Mem^ := Len;
  Inc(Mem, 1);

  Move(aString[1], Mem^, Len);
  PByte(Mem)[Len + 1] := 0;    // make sure it is null terminated

  Result := Mem;
end;

function BuiltOldAnsiString(const aString: string): Pointer; overload;
begin
  Result := BuiltOldAnsiString(AnsiString(aString));
end;

function BuiltOldAnsiStringMt(const aString: AnsiString): Pointer; overload;
var
  Len: Integer;
  Mem: PCardinal;
begin
  Len := Length(aString);
  if Len = 0 then
  begin
    Result := nil;
    Exit;
  end;

  SetLength(gTempBufferForEmulatedOldAnsiThreadSafe, Len + 8 + 1); // header + 1 null ansi char
  Mem := @gTempBufferForEmulatedOldAnsiThreadSafe[0];
  Mem^ := $FFFFFFFF;           // refcount =(-1) emulating constant string
  Inc(Mem, 1);
  Mem^ := Len;
  Inc(Mem, 1);

  Move(aString[1], Mem^, Len);
  PByte(Mem)[Len + 1] := 0;    // make sure it is null terminated

  Result := Mem;
end;

function BuiltOldAnsiStringMt(const aString: string): Pointer; overload;
begin
  Result := BuiltOldAnsiString(AnsiString(aString));
end;
Would love to know if this works ?
Kas
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: DLL mit Strings von D10 nach Delphi 6

  Alt 27. Okt 2023, 12:02
Man könnte den StrRec-Record aus der System.pas benutzen, um sich die Stringkonstante zu bauen, wenn Emba sich nicht vehement weigern würde ihn öffentlich zu machen.

Ja, Wenn RefCount = -1, dann wird es als Konstante behandelt, also Funktionen, welche die Variable kopieren oder freiheben würden, würden es entsprechend beachten.
  • von D10 zu D7 gäbe es keine Problene (da das alte Format im Neuen enthalten ist und hier der Offset für die Speicherverwaltung egal wäre)
  • von D7-DLL zurück ins D10, da muß die Konstante natürlich dem D10-Format entsprechen
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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:12 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz