Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Delphi DLL String übergeben (https://www.delphipraxis.net/214868-delphi-dll-string-uebergeben.html)

DelTurbo 28. Mär 2024 09:46

AW: Delphi DLL String übergeben
 
Huhu,
es tut mir leid aber ich muss nochmal "Nerven". Ich hole mir einen String (die Antwort) folgendermaßen aus der DLL. Ist der String 2000 Lang klappt alles. Irgendwo bei 2500 liegt die grenze ab der ich dann komischerweise ein "Out of Memory" bekomme. Also 3000 Zeichen geht gar nicht. Ich versuche mal den Source wo es "knallt" hier zu Posten. Das ist ein kleines Testprogramm, dort kann ich die länge von dem String den haben möchte übergeben.

In der DLL mache ich das...
Delphi-Quellcode:
var
  Answer   :WideString;

procedure GetTxt(A:PWideChar;L:Integer); cdecl;
var
  i    :Integer;
begin
    Answer:='';
    for i:=0 to L-1 do begin
      Answer:=Answer+'A';
    end;
    Move(Answer,A^,Length(Answer));
end;
Im Programm das...
Delphi-Quellcode:
procedure TfMain.btnGetTxtClick(Sender: TObject);
var
  line   :WideString;
begin
    SetLength(Antwort,StrToInt(edtTextLen.Text));
    GetTxt(@Antwort,StrToInt(edtTextLen.Text));
    SetString(line,PWideChar(@Antwort[0]),Length(Antwort)); // hier geht es in die Hose. Wie gesagt ab ca. 2500 Zeichen. Bei 2000 klappt es
end;
Ich habe gestern wie wild gegoogelt aber ich finde nichts. Es spielt auch keine Rolle ob die DLL mit Delphi 10.4 oder 2007 erstellt wurde.

Vielen Dank im voraus

himitsu 28. Mär 2024 09:54

AW: Delphi DLL String übergeben
 
0 ist definitiv falsch:!:

Delphi-Quellcode:
PWideChar(@Antwort[1])
oder besser
Delphi-Quellcode:
PWideChar(@Antwort[Low(string)])
(für die kurze Era wo das mal im Mobilen-Delphi ausprobiert wurde)
oder einfach nur direkt
Delphi-Quellcode:
PWideChar(Antwort)
, denn Ersteres knallt dir bei einem leeren String (Length=0) gnadenlos eine Exception entgegen.
https://docwiki.embarcadero.com/RADS...rings_(Delphi)



Für AnsiString's und UnicodeString/String müsste ShareMem verwendet werden, oder eben als PChar übergeben.

Wenn keine #0 im PChar/PWideChar oder PAnsiChar vorkommen, dann braucht man keine Länge einzeln zu übergeben.
MSDN-Library durchsuchenStrLen

Für WideString geht es geht es auch direkt, da es nicht den DelphiMM benutzt, sondern den MemoryManager vom OLE32
und intern ist es eigentlich ein Bei Google suchenBSTR, wofür automatisch die API um MSDN-Library durchsuchenSysAllocString/SysFreeString verwendet wird, welche auch C++ und Co. nutzen können.
Außerdem nutzt es somit auch eine Art von ShareMem (nur halt nicht das vom Delphi), weswegen es keine Probleme mit DLLs und COM-Interfaces gibt.

himitsu 28. Mär 2024 09:56

AW: Delphi DLL String übergeben
 
Zitat:

Zitat von DelTurbo (Beitrag 1535066)
hier geht es in die Hose. Wie gesagt ab ca. 2500 Zeichen. Bei 2000 klappt es

Ich wüsste nicht, warum SetString eine Begrenzung haben sollte. :gruebel:

System._UStrFromPWCharLen für String/UnicodeString
System._WStrFromPWCharLen für WideString

[edit]
Arg, wer hat sich denn diesen totalen Schwachsinn ausgedacht?
Für WideString ist SetString komplett im A***

Echt mal, das einfach blind nach UnicodeString zu casten, ist grob fahrlässig ... hatte wohl auch wer mitbekommen und desswegen die Compilerwarnung via Pointer unterdrückt.
[/edit]

[edit2] Neee, das ist nur für Nicht-Windowse (iOS/ISX/Android/Linux), wo WideString heimlich ein UnicodeString ist. :oops:



So oder so, warum nimmst du nicht einfach
Delphi-Quellcode:
Line := A;
und lässt das mit dem Len weg?
Oder eben direkt WideString als Parameter nutzen.
Delphi-Quellcode:
procedure GetTxt(const A: WideString); cdecl;


Und wozu das cdecl? (möglicher Aufruf aus C++ oder so?)

DelTurbo 28. Mär 2024 10:17

AW: Delphi DLL String übergeben
 
Ich wollte nun sofort wenn ich aus der DLL wieder komme die Length(Antwort) ausgeben. Schon dabei scheppert es. Wenn ich mir den String Antwort im Debugger ansehe ist er meines Erachtens richtig. Auch eine Zusätzliche 0 am ende ändert nichts an der Sache. :(

Edit: @himitsu, Problem war am Anfang das die DLL unter Delphi 10.4 erstellt werden muss, ich aber mit Delphi 2007 arbeite. Da wurd ja ab Delphi 2009 etwas an den Strings geändert. "Rolf Frei" hat mich denn erstmal auf den richtigen Weg gebracht.

himitsu 28. Mär 2024 10:22

AW: Delphi DLL String übergeben
 
nochmal
Zitat:

0 ist definitiv falsch :!:
ShortString: an Adresse 0 steht das LängenByte (ist intern ein Array[0..255] of AnsiChar),
und deswegen fangen auch neueren LongStrings (AnsiString und UnicodeString) seit 20 Jahren mit 1 an zu zählen.

Mit [0] schreibst zu in AdressOffest -1, also mitten in die Verwaltungsdaten, wo zufällig der Längen-Integer sich versteckt.

DelTurbo 28. Mär 2024 10:25

AW: Delphi DLL String übergeben
 
Das mit der 0 habe ich schon geändert. Oder ist auch das Move(Answer,A^,Length(Answer)); in der DLL Falsch? Wenn ja, wie komme ich auf A^ + 1? Also A^+1 geht nicht.

DelTurbo 28. Mär 2024 10:31

AW: Delphi DLL String übergeben
 
Ups :oops:

Das im Programm habe ich falsch dargestellt. Das sieht so aus...

Delphi-Quellcode:
var
  Antwort  :array of Char;

procedure TfMain.btnGetTxtClick(Sender: TObject);
var
  line   :WideString;
begin
    SetLength(Antwort,StrToInt(edtTextLen.Text));
    GetTxt(@Antwort,StrToInt(edtTextLen.Text));
    SetString(line,PWideChar(@Antwort[1]),StrToInt(edtTextLen.Text)); //Length(Antwort));

himitsu 28. Mär 2024 15:03

AW: Delphi DLL String übergeben
 
dynamisches Array:

Delphi-Quellcode:
@Antwort
ist ein Zeiger auf die Variable, nicht auf die Daten.
Delphi-Quellcode:
@Antwort[0]
ist ein Zeiger auf das erste Char, bzw. auf alle Chars im Array.

Wie gesagt, mach doch einfach
Delphi-Quellcode:
procedure GetTxt(var A: WideString; L: Integer); cdecl;
und lass das ganze Rumgepointere sein.

Delphi-Quellcode:
procedure GetTxt(var A: WideString; L: Integer); cdecl;
var
  i :Integer;
begin
  ...
  A := Answer;
end;
Dann kann auch diese beschissene globale Variable weg.

DelTurbo 28. Mär 2024 15:06

AW: Delphi DLL String übergeben
 
Hi,
danke dir habe es auf stdcall umgestellt. Läuft nun. Natürlich ohne Pointer :thumb:

Rolf Frei 28. Mär 2024 15:48

AW: Delphi DLL String übergeben
 
Du kannst ganz normal mit Strings arbeiten und benötigst kein Array of Char. Der Compiler nimmt dir da sehr viel Konvertierungsarbeit ab, wenn du es richtig machst. Ausserdem ist dir anscheinend nicht recht klar was der Unterschied von Unicode und Ansi ist. In Ansi (D2007) ist eine Zeichen (Char) ein Byte. Bei Unicode ist ein Zeichen (Char) 2 Byte. Du kannst also bei einem Speicher Movebefehl nicht einfach die Länge des String nehmen, da das dann zu wenig Speicher ist.

Delphi-Quellcode:
Move(Answer,A^,Length(Answer));
Das ist devinitv in der DLL falsch. Length(Answer) liefet dir die Anzahl Zeichen in Answer, aber du benötigst die Anzahl Bytes. Das muss daher so sein:
Delphi-Quellcode:
Move(Answer[1],A[0],Length(Answer) * SizeOf(Char));
Leider ist mir nicht mehr so recht klar, was du nun wo genau machst. Die DLL ist immer noch mit D10.4 geschrieben? Wenn ja darfst du da keine WideStrings nutzen sondern ganz normal mit String und Char arbeiten. WideString und PWideChar bezieht sich nur auf D2007.

D10.4 DLL:
Delphi-Quellcode:
var
  Answer :String;

procedure GetTxt(A:PChar;L:Integer); cdecl;
var
  i :Integer;
 
begin
    Answer:=StringOfChar('A', L);
    SetLength(A, L);
    Move(Answer[1],A[0],Length(Answer) * SizeOf(Char)); // benötigen hier Bytes nicht Zeichen!!!
end;
D2007 Anwendung:
Delphi-Quellcode:
var
  Antwort :String; // Dein D2007 kann in den TEdits, etc. eh kein Unicode nutzen, da macht es keinen Sinn mit WideString als Resultat.

procedure TfMain.btnGetTxtClick(Sender: TObject);
var
  wAntwort: Array of PWideChar;
begin
    SetLength(wAntwort,StrToInt(edtTextLen.Text));
    GetTxt(wAntwort[0],StrToInt(edtTextLen.Text));
    Antwort := String(WideString(wAntwort));   // Eventuell geht es auch nur mit String(wAntwort)


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:03 Uhr.
Seite 2 von 3     12 3      

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