![]() |
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:
Im Programm das...
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;
Delphi-Quellcode:
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.
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; Vielen Dank im voraus |
AW: Delphi DLL String übergeben
0 ist definitiv falsch:!:
Delphi-Quellcode:
oder besser
PWideChar(@Antwort[1])
Delphi-Quellcode:
(für die kurze Era wo das mal im Mobilen-Delphi ausprobiert wurde)
PWideChar(@Antwort[Low(string)])
oder einfach nur direkt
Delphi-Quellcode:
, denn Ersteres knallt dir bei einem leeren String (Length=0) gnadenlos eine Exception entgegen.
PWideChar(Antwort)
![]() 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. ![]() 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 ![]() ![]() 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. |
AW: Delphi DLL String übergeben
Zitat:
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:
und lässt das mit dem Len weg?
Line := A;
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?) |
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. |
AW: Delphi DLL String übergeben
nochmal
Zitat:
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. |
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.
|
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)); |
AW: Delphi DLL String übergeben
dynamisches Array:
Delphi-Quellcode:
ist ein Zeiger auf die Variable, nicht auf die Daten.
@Antwort
Delphi-Quellcode:
ist ein Zeiger auf das erste Char, bzw. auf alle Chars im Array.
@Antwort[0]
Wie gesagt, mach doch einfach
Delphi-Quellcode:
und lass das ganze Rumgepointere sein.
procedure GetTxt(var A: WideString; L: Integer); cdecl;
Delphi-Quellcode:
Dann kann auch diese beschissene globale Variable weg.
procedure GetTxt(var A: WideString; L: Integer); cdecl;
var i :Integer; begin ... A := Answer; end; |
AW: Delphi DLL String übergeben
Hi,
danke dir habe es auf stdcall umgestellt. Läuft nun. Natürlich ohne Pointer :thumb: |
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:
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:
Move(Answer,A^,Length(Answer));
Delphi-Quellcode:
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.
Move(Answer[1],A[0],Length(Answer) * SizeOf(Char));
D10.4 DLL:
Delphi-Quellcode:
D2007 Anwendung:
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;
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. |
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