Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   DLL mit Strings von D10 nach Delphi 6 (https://www.delphipraxis.net/213949-dll-mit-strings-von-d10-nach-delphi-6-a.html)

Kas Ob. 26. Okt 2023 08:28

AW: DLL mit Strings von D10 nach Delphi 6
 
Thinking more :gruebel:

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 Ob. 27. Okt 2023 11:12

AW: DLL mit Strings von D10 nach Delphi 6
 
@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 ?

himitsu 27. Okt 2023 12:02

AW: DLL mit Strings von D10 nach Delphi 6
 
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


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:34 Uhr.
Seite 2 von 2     12   

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