Einzelnen Beitrag anzeigen

Der schöne Günther

Registriert seit: 6. Mär 2013
6.158 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: DLL Verständnis frage...

  Alt 28. Mär 2024, 16:04
Nein, du würdest den String dann z.B. als simples Byte-Array mit definiertem Encoding (z.B. ASCII, oder UTF-16 oder was auch immer) da reinschreiben. Das müsste man einmal festlegen, damit DLL und DLL-Benutzer alle nach den gleichen Regeln spielen.

Nicht 1:1 den den Speicher rüberkopieren, denn das ist ja spezifisch nach deiner aktuellen Delphi-Version. Sondern ein definiertes Byte-Array.

Beispiel für beide Seiten (String in DLL übertragen, und String wieder rausholen)

Delphi-Quellcode:
program Project1;

uses System.SysUtils;

var text_in_dll: String;

function createLongString(): String;
begin
   const NUMBER_OF_LINES = 10_000;
   const LINE_LENGTH = 7; // 5 for "Hello", 2 for line break
   const stringBuilder = TStringBuilder.Create(NUMBER_OF_LINES * LINE_LENGTH);
   try
      for var lineNumber := 0 to Pred(NUMBER_OF_LINES) do
         stringBuilder.AppendLine('Hello');
      Result := stringBuilder.ToString();
   finally
      stringBuilder.Destroy();
   end;
end;

// accepts UTF-8 encoded strings
procedure acceptString(const numberOfBytes: NativeInt; const firstByte: PByte); stdcall;
begin
   var bytes: TBytes;
   SetLength(bytes, numberOfBytes);
   System.Move(firstByte^, bytes[0], numberOfBytes);

   text_in_dll := TEncoding.UTF8.GetString(bytes);
end;

// Ist der Rückgaberwert False, dann war wohl "bufferLength" zu
// schmal und sollte so groß sein, wie "bytesWritten" angibt
function getString(
   out firstByte: PByte;
   const bufferLength: NativeInt;
   out bytesWritten: NativeInt
): Boolean; stdcall;
begin
   bytesWritten := 0;
   if(text_in_dll.IsEmpty()) then
      Exit(False);

   var bytes := TEncoding.UTF8.GetBytes(text_in_dll);
   bytesWritten := Length(bytes);

   if(bufferLength < bytesWritten) then
      Exit(False);

   System.Move(bytes[0], firstByte^, bytesWritten);
   Result := True;
end;

procedure sendStringToDll();
begin
   var longString := createLongString();
   var bytes := TEncoding.UTF8.GetBytes(longString);

   acceptString( Length(bytes), Addr(bytes[0]) );
end;

procedure receiveStringFromDll();
begin
   var buffer: TBytes;
   var bufferLength: NativeInt;
   SetLength(buffer, 5_000);
   var firstByte: PByte := Addr(buffer[0]);

   if(not getString({out} firstByte, Length(buffer), {out} bufferLength)) then
      WriteLn('Buffer war zu kurz, muss ', bufferLength, ' lang sein');

   SetLength(buffer, bufferLength);
   firstByte := Addr(buffer[0]);
   getString({out} firstByte, Length(buffer), {out} bufferLength);

   const asText = TEncoding.UTF8.GetString(buffer, 0, bufferLength);
   Writeln('Text received from DLL:' + sLineBreak + asText);
end;

begin
   sendStringToDll();
   receiveStringFromDll();
end.
Ich habe das Gefühl das ginge auch besser, aber so würde ich das machen.

Geändert von Der schöne Günther (28. Mär 2024 um 16:32 Uhr)
  Mit Zitat antworten Zitat