![]() |
AW: Array über Schleife ausfüllen
:roll:
Bitte, Bitte...wie ist es richtig? :cry: Zitat:
Delphi-Quellcode:
FParameters[6] := PAnsiChar(AnsiString(FileList[0]));
|
AW: Array über Schleife ausfüllen
Du muß die generierten AnsiString für jede Zeilen bis zum Ende von PDFMerge gespeichert haben, (also irgendwo genügend AnsiString-Variablen für jedes Item)
dann bleiben die PAnsiChar-Referenzen auch so lange gültig. (alternativ kann man auch an der Referenzzählung rumpfuschen ... und Dieses am Ende wieder rückgängig, weil sonst Speicherleck) Oder du erstellst eben für jeden PAnsiChar einen eigenen Speicher, wie z.B. mit
Delphi-Quellcode:
. (am Ende dann DisposeStr, weil wegen Speicherleck)
NewStr
Oder eben du änderst die Signatur deiner Funktion, oder castest beim Aufruf das Array. Dann könnte man auch mit einem Array-of-AnsiString arbeiten, wo dieses Array dann seine eigenen String-Referenzen hat, damit im nächsten Durchlauf die alten "Kopien" weiterhin gültig bleiben. Oder mit zwei Arrays arbeiten ... einmal mit AnsiString für die String-Referenzen und die Kopie als PAnsiChar auf die jeweiligen AnsiStringArrayItems. |
AW: Array über Schleife ausfüllen
Um das Problem mal zu veranschaulichen:
Delphi-Quellcode:
Der Result von GetP ist quasi in dem Moment schon ungültig, wo er zurückgegeben wird, weil er auf irgendwo auf den Stack zeigt - und zwar auf eine Stelle, die nicht mehr gültig ist.
program Project773;
{$APPTYPE CONSOLE} function GetP(S: string): PAnsiChar; begin Result := PAnsiChar(AnsiString(S)); end; var P1: PAnsiChar; P2: PAnsiChar; begin P1 := GetP('Hallo Welt'); Writeln('P1:', P1); P2 := GetP('Hurz'); Writeln('P1:', P1); Writeln('P2:', P2); Readln; end. |
AW: Array über Schleife ausfüllen
Liste der Anhänge anzeigen (Anzahl: 1)
Danke an Alle...:P
Mit den Informationen habe ich es dann auch geschnallt. :oops: Zitat:
Jetzt geht es: :P Zwischenspeicherung in TList<AnsiString>
Delphi-Quellcode:
function TSEAMGhostscript.PDFMerge(FileName: string; FileList: TStrings): Boolean;
var ParametersTemp: TList<AnsiString>; InitError: Integer; procedure CreateMergeFiles; var I: Integer; begin for I := 0 to FileList.Count - 1 do begin ParametersTemp.Add(AnsiString(FileList[I])); // <-- FParameters[I + 6] := PAnsiChar(ParametersTemp[I]); // <-- end; end; begin if FDLLHandle = 0 then begin if not LoadDLL(FDLLPath) then begin Result := False; Exit; end; end; try ParametersTemp := TList<AnsiString>.Create; //<-- try SetLength(FParameters, FileList.Count + 6); FParameters[0] := ''; FParameters[1] := '-dNOPAUSE'; FParameters[2] := '-dBATCH'; FParameters[3] := '-dPDFSETTINGS=/ebook'; FParameters[4] := '-sDEVICE=pdfwrite'; FParameters[5] := PAnsiChar(AnsiString('-sOutputFile=' + FileName)); CreateMergeFiles; InitError := FGsApiInitWithArgs(FGsInstance, Length(FParameters), FParameters); Result := (InitError = 0); if InitError <> 0 then begin if Assigned(FOnError) then begin FOnError(Self, Format('Fehlercode: %d', [InitError])); end; end; finally ParametersTemp.Free; end; finally FGsApiExit(FGsInstance); end; if not Result then begin if Assigned(FOnError) then begin FOnError(Self, Format('Fehler beim Erstellen: %s', [FileName])); end; end; end; |
AW: Array über Schleife ausfüllen
Hach, an was man sich so alles gewöhnen könnte.
![]()
Delphi-Quellcode:
bzw.
Temp: TArray<AnsiString>;
for S in FileList do begin Temp := Temp + [AnsiString(S)]; FParameters := FParameters + [PAnsiChar(Temp[High(Temp)])]; ... SetLength(FParameters, FileList.Count); // die 6 Zusätzlichen jetzt noch nicht dazu // Und am Ende gibt sich Temp von selber frei.
Delphi-Quellcode:
Temp := ['-sOutputFile=' + FileName];
FParameters := [ '', '-dNOPAUSE', '-dBATCH', '-dPDFSETTINGS=/ebook', '-sDEVICE=pdfwrite', PAnsiChar(Temp[0])]; for S in FileList do begin Temp := Temp + [S]; // implizit ein + [AnsiString(S)]; FParameters := FParameters + [PAnsiChar(Temp[High(Temp)])]; end; Aber wie gesagt, ich würde FGsApiInitWithArgs einfach ein TArray<AnsiString> geben, anstatt einem TArray<PAnsiChar>, und mir den ganzen PChar-Quatsch einfach schenken.
Delphi-Quellcode:
FParameters := [
'', '-dNOPAUSE', '-dBATCH', '-dPDFSETTINGS=/ebook', '-sDEVICE=pdfwrite', '-sOutputFile=' + FileName]; for S in FileList do FParameters := FParameters + [S]; // wäre beides String gewesen, dann ginge sogar sowas FParameters := ['', '-dNOPAUSE', '-dBATCH', '-dPDFSETTINGS=/ebook', '-sDEVICE=pdfwrite', '-sOutputFile=' + FileName] + FileList.ToStringArray; Rein "technisch" bestünde sogar die Möglichkeit in einen "String" einen "AnsiString" reinzumachen, da die LongStrings in Delphi sowohl CodePage als auch CharSize im String speichern. Also in einer TStringList die Codierung der "Strings" auf ANSI umzuschreiben. (ich weiß aber nicht, in wie weit die anfangs mit Delphi2009 eingeführten Casts noch aktiv sind, weil die waren arschlangsam, wenn "überall" bei jeder Stringzuweisung/Auslesen die Kodierung geprüft wird) Ist aber nur was für echt Hartgesottene:
Delphi-Quellcode:
// CP_ACP: TStringList -> intern schonmal die CodePage ändern -> TArray<String> -> TArray<AnsiString>
// CP_UTF8: TStringList -> intern schonmal die CodePage ändern -> TArray<String> -> TArray<UTF8String> type TStringListAccess = class(TStrings) FList: TStringItemList; end; var SL: TStringList; AA: TArray<AnsiString>; begin SL := TStringList.Create; SL.Add('123'); SL.Add('äöü'); {for var i := SL.Count-1 downto 0 do begin var S := SL[i]; SetCodePage(RawByteString(Pointer(S)), CP_UTF8, True); // CP_ACP für ANSI SL[i] := S; end;} for var i := SL.Count-1 downto 0 do SetCodePage(RawByteString(Pointer(TStringListAccess(SL).FList[i].FString)), CP_UTF8, True); // CP_ACP für ANSI AA := TArray<AnsiString>(SL.ToStringArray); |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:13 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