Det korte svar på den supportsag er ja, med grænser. HotPDF 2.730.0 bygges på Free Pascal 3.2.2 og Lazarus 4.6 til Win64, og kerneoprettelses-, indlæsnings- og lagringsstierne virker. Det, der ikke følger med, er alt, der hviler på et statisk linket native codec-objekt eller på Delphi anonymous methods
Spørgsmålet ankommer normalt på samme måde: et team standardiserer på Lazarus til et cross-platform-værktøj, eller arver en Free Pascal-kodebase og vil have samme PDF-komponent, de allerede licenserer til Delphi. At portere et modent Delphi-bibliotek er sjældent et spørgsmål om syntaks. Den interessante del er, hvad porteringen afslører om, hvor biblioteket stiltiende var koblet til én toolchain, og i dette tilfælde sidder koblingen to helt specifikke steder: objektfil-ABI'en for de medfølgende codecs og compilerfunktionerne, der gemmer sig bag et versionssymbol
Hvad Free Pascal 3.2.2 behøver, før HPDFDoc kompilerer
HotPDF kompilerer under Free Pascal kun i Delphi mode, og kun når Lazarus LCL-unit-mapperne er på søgestien. Ingen af delene kan forhandles. HotPDF.inc skifter compileren med {$MODE DELPHI} og {$H+} inde i sin {$IFDEF FPC}-blok og nægter alt ældre med en {$FATAL}, når FPC_FULLVERSION er under 30202, så en 3.0.x-installation fejler højt i stedet for at producere en ødelagt unit. Lazarus runtime-pakken HotPDFLaz.lpk koder resten: LCL som en påkrævet pakke og -Mdelphi som en tilpasset indstilling
LCL-kravet overrasker folk, der kun vil have konsoloutput, men det er strukturelt. HPDFFPCCompat leverer Delphi VCL-typerne, som Free Pascal ikke har nogen ækvivalent til, mapper TMetafile og TMetafileCanvas på LCL bitmap- og canvas-klasser og aliaser TRichEdit til TMemo, mens HPDFDoc aliaser TPNGObject til Graphics.TPortableNetworkGraphic. Behandl dem som compile-time-shims, ikke feature-paritet: en metafile-klasse understøttet af en bitmap holder uniten kompilerende, den gør ikke metafile-stierne til at opføre sig, som de gør på Delphi. Selv den ikke-GUI smoke test trækker Interfaces ind, og build-scriptet giver -Fu for lcl\units\x86_64-win64 og lazutils-outputmappen
Hvorfor D2009+ ikke kan fungere som versionsport
Det er fristende at behandle Free Pascal-builden som en moderne compiler og blot definere det nyeste Delphi-featuresymbol. HotPDF gør ikke, og årsagen er værd at sige rent ud: D2009+ betyder ikke kun Unicode-strenge, den gælder også for units, hvis offentlige API er udtrykt med anonymous methods. Free Pascal 3.2.2 understøtter hverken Delphi anonymous methods eller de API'er, så at låne symbolet ville trække kode ind, der ikke kan kompile. Uses-clausen i HPDFDoc bærer derfor to separate betingede haler, og overlapningen mellem dem er bevidst snarere end tilfældig
uses
// ...
HPDFJavaScript,
HPDFFormCalcGraph
{$IFDEF FPC}
, HPDFFPCCodecStubs,
HPDFCMS,
HPDFWinCertSigner
{$ENDIF}
{$IFDEF D2009+}
, HPDFXFARuntime,
HPDFCMS,
HPDFWinCertSigner,
HPDFSignVerify,
HPDFSignatureBatch
{$ENDIF};
Hvorfor stopper de native codecs ved linkeren?
Fordi de er Win64 COFF-objekter udsendt af én bestemt toolchain, og ingen af Free Pascal-linkerne på Win64 vil indtage dem: hverken den interne linker eller den eksterne GNU ld-sti. Dette er et objektfil-ABI-problem, ikke et Pascal-problem, og ingen mængde betinget kildekode fikser det. Biblioteket tager den eneste ærlige rute til rådighed. Hvert {$L}-direktiv, der trækker et statisk codec-objekt ind, er pakket ind i {$IFNDEF FPC}, så Free Pascal-builden blot udelader dem, og HPDFFPCCodecStubs leverer derefter hvert manglende eksternt symbol som en stub, der rejser i stedet for at returnere
// HPDFFPCCodecStubs.pas
function HPDFFPCNativeCodecUnavailable: PtrUInt;
begin
raise ENotSupportedException.Create(
'This native codec is not available in the Free Pascal build');
end;
function HPDFFPCStub_deflate: PtrUInt; cdecl;
public name 'deflate';
begin
Result := HPDFFPCNativeCodecUnavailable;
end;
Den stub-tabel er lang, og at læse den fortæller dig præcis, hvilke evner der er Delphi-only i dag: zlib-ng- og zopfli-deflate-indgangspunkterne, libjpeg-komprimering og -dekomprimering, OpenJPEG JPEG 2000-codecet, libtiff og dets per-komprimering-initialiserere, JBIG2 encode og decode, Little-CMS-farvetransformationsindgangspunkterne og AES-primitiverne. Designvalget bag stubberne betyder mere end listen. Et manglende symbol ved link-tid giver dig en væg af undefined references fra en unit, du aldrig rørte; en stub, der rejser ENotSupportedException, giver dig en build, der kører, en besked, der navngiver årsagen, og et stack trace, der peger på kaldstedet. Det betyder også, at en Free Pascal-build aldrig stiltiende producerer forkerte bytes, hvor en Delphi-build ville producere korrekte. Bemærk også andenordenseffekten: kørsel af ikke-betroede image-codecs i en isoleret proces er en beslutning, der kun opstår på Delphi-builden, fordi en Free Pascal-build slet ikke har nogen in-process native decoder at sandboxe
Komprimering: den første linje at ændre er cmNone
Før du porterer noget andet, sæt Compression til cmNone. THPDFCompressionMethod tilbyder præcis to værdier, cmNone og cmFlateDecode, og den anden ruter direkte ind i deflate-indgangspunkterne, der er stubber i en Free Pascal-build. Verificér først kerneobjektmodellen med komprimering slået fra, og beslut derefter, hvad du ellers behøver. Det er den orden, den medfølgende smoke test bruger: opret et en-sides ukomprimeret dokument, genindlæs det og assert, at sideantallet kom tilbage som ét. Ukomprimeret output er større, og det er stadig en helt gyldig PDF
program HotPDFLazarusSmoke;
{$mode delphi}
{$H+}
uses
Interfaces, SysUtils, HPDFDoc;
var
Pdf, Reloaded: THotPDF;
OutputFile: string;
PageCount: Integer;
begin
OutputFile := IncludeTrailingPathDelimiter(GetTempDir) +
'HotPDF-FPC-Smoke.pdf';
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := OutputFile;
Pdf.Compression := cmNone; // cmFlateDecode rammer et stubbet symbol
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 12);
Pdf.CurrentPage.TextOut(72, 72, 0, 'HotPDF Free Pascal smoke test');
Pdf.EndDoc;
finally
Pdf.Free;
end;
Reloaded := THotPDF.Create(nil);
try
PageCount := Reloaded.LoadFromFile(OutputFile);
if PageCount <> 1 then
raise Exception.CreateFmt('Expected one page, got %d', [PageCount]);
finally
Reloaded.Free;
end;
end.
Hvad sker der med parallel side-rendering?
Den kompilerer stadig, returnerer stadig korrekte bitmaps og holder op med at være parallel. THotPDF.RenderLoadedPagesParallel og THotPDF.RenderLoadedPagesParallelOrdered er bygget på TThread.CreateAnonymousThread med en inline procedure-closure, som Free Pascal 3.2.2 ikke kan udtrykke, så Free Pascal-grenen kører en deterministisk seriell fallback: den går sideindekserne i orden igennem, kalder RenderLoadedPageToBitmap for hver og tæller succeserne. API-formen, returværdien og output-arrayet er uændret, hvilket er det, der lader en enkelt kodebase bygge begge veje
var
Bitmaps: THPDFBitmapArray;
Info: THPDFParallelRenderPipelineInfo;
Rendered: Integer;
begin
Rendered := Pdf.RenderLoadedPagesParallel([0, 1, 2, 3], 150, 4,
Bitmaps, Info);
// Delphi: Info.WorkerCount er, hvad hukommelsesbudgettet tillod
// Free Pascal: Info.WorkerCount er altid 1, sider i indeksorden
if Info.WorkerCount = 1 then
LogSerialFallback(Rendered, Info.RequestedWorkerCount);
Fallbacken er ikke stille, hvilket er den del, der er værd at designe omkring. Den fylder THPDFParallelRenderPipelineInfo ærligt: PageCount fra anmodningen, RequestedWorkerCount ekkoende hvad du bad om, WorkerCount sat til 1, og de fuldførte og leverede tællere matchende det, der reelt kom tilbage. Kode, der allerede inspicerer Info for at størrelsesbestemme en progressbar eller et hukommelsesbudget, fortsætter med at virke og læser sandheden snarere end en antagelse. Hvis din gennemløbsplan afhænger af parallel-render-pipelinen og dens backpressure-model, er den plan en Delphi-plan; på Free Pascal, budgetter for den enkelttrådede omkostning ved rendering af en side til en bitmap ganget med sideantallet
Hvilken build bør du reelt skibe?
Vælg efter evne, ikke efter præference. Hvis dit workflow er dokumentsamling, tekst- og vektortegning, formularudfyldning, indlæsning og lagring, dækker Free Pascal-builden på Win64 det, og du bør validere med komprimering slået fra, før du slår noget til. Hvis det involverer JPEG-, JPEG 2000-, TIFF- eller JBIG2-billeder, ICC-farvetransformationer, komprimeret output eller gennemløb, der afhænger af mange kerner, bliv på Delphi eller C++Builder indtil videre. Grænsen trækkes af en objektfil-ABI og en manglende sprogfeature, som begge er synlige i kilden snarere end begravet i en supportmatrix, og som begge fejler med en navngiven fejl snarere end et forkert resultat
Free Pascal- og Lazarus-pakken leveres i samme distribution som Delphi- og C++Builder-units, så en licens dækker begge, og du kan teste Lazarus-stien mod dine egne dokumenter, før du binder dig; HotPDF Delphi PDF Component-produktsiden bærer den aktuelle compiler-supportmatrix og den fulde API-reference