Het korte antwoord op dat supportticket is ja, met beperkingen. HotPDF 2.730.0 bouwt op Free Pascal 3.2.2 en Lazarus 4.6 voor Win64, en de kernpaden voor create, load en save werken. Wat niet meekomt is alles wat rust op een statisch gelinkt native codec-object of op Delphi-anonieme methoden
De vraag komt meestal op dezelfde manier binnen: een team standaardiseert op Lazarus voor een cross-platform tool, of erft een Free Pascal-codebase en wil dezelfde PDF-component waarvoor het al een licentie heeft voor Delphi. Een volwassen Delphi-bibliotheek porten is zelden een kwestie van syntaxis. Het interessante is wat de port blootlegt over waar de bibliotheek stilletjes aan één toolchain vastzat, en in dit geval zit die koppeling op twee heel specifieke plaatsen: de object-file-ABI van de meegeleverde codecs, en de compilerfuncties die zich achter een versiesymbool verschuilen
Wat Free Pascal 3.2.2 nodig heeft voordat HPDFDoc compileert
HotPDF compileert onder Free Pascal alleen in Delphi-modus, en alleen wanneer de Lazarus LCL-unitmappen op het zoekpad staan. Geen van beide is onderhandelbaar. HotPDF.inc zet de compiler met {$MODE DELPHI} en {$H+} binnen zijn {$IFDEF FPC}-blok en weigert alles ouder met een {$FATAL} wanneer FPC_FULLVERSION onder 30202 zit, dus een 3.0.x-installatie faalt luid in plaats van een kapotte unit op te leveren. Het Lazarus-runtimepakket HotPDFLaz.lpk codeert de rest: LCL als verplicht pakket en -Mdelphi als custom option
De LCL-eis verrast mensen die alleen console-uitvoer willen, maar hij is structureel. HPDFFPCCompat levert de Delphi-VCL-types waar Free Pascal geen equivalent voor heeft, door TMetafile en TMetafileCanvas op LCL-bitmap- en canvasclasses te mappen en TRichEdit alias te geven naar TMemo, terwijl HPDFDoc TPNGObject aliast naar Graphics.TPortableNetworkGraphic. Behandel die als compile-time shims, niet als pariteit: een metafileclass met een bitmap eronder houdt de unit compilerend, het laat de metafilepaden zich niet gedragen zoals op Delphi. Zelfs de niet-GUI smoke test trekt Interfaces mee, en het buildscript geeft -Fu mee voor lcl\units\x86_64-win64 en de lazutils-uitvoermap
Waarom D2009+ niet tegelijk als versiepoort kan dienen
Het is verleidelijk om de Free Pascal-build als een moderne compiler te behandelen en simpelweg het nieuwste Delphi-featuresymbool te definiëren. HotPDF doet dat niet, en de reden is het uitspreken waard: D2009+ betekent niet alleen Unicode-strings, het poortt ook units waarvan de publieke API met anonieme methoden is uitgedrukt. Free Pascal 3.2.2 ondersteunt noch Delphi-anonieme methoden, noch die API's, dus het lenen van het symbool zou code binnenslepen die niet kan compileren. De uses-clausule van HPDFDoc draagt daarom twee aparte conditionele staarten, en de overlap daartussen is opzet in plaats van toeval
uses
// ...
HPDFJavaScript,
HPDFFormCalcGraph
{$IFDEF FPC}
, HPDFFPCCodecStubs,
HPDFCMS,
HPDFWinCertSigner
{$ENDIF}
{$IFDEF D2009+}
, HPDFXFARuntime,
HPDFCMS,
HPDFWinCertSigner,
HPDFSignVerify,
HPDFSignatureBatch
{$ENDIF};
Waarom stoppen de native codecs bij de linker?
Omdat het Win64 COFF-objecten zijn die door één specifieke toolchain zijn uitgegeven, en geen van beide Free Pascal-linkers op Win64 ze wil consumeren: niet de interne linker, niet het externe GNU ld-pad. Dit is een object-file-ABI-probleem, geen Pascal-probleem, en geen hoeveelheid conditionele broncode lost het op. De bibliotheek neemt de enige eerlijke route die beschikbaar is. Elke {$L}-directive die een statisch codec-object binnenhaalt zit in {$IFNDEF FPC}, dus de Free Pascal-build laat ze gewoon weg, en HPDFFPCCodecStubs levert daarna elk ontbrekend extern symbool als een stub die een exceptie gooit in plaats van terug te keren
// 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;
Die stubtabel is lang, en als u hem leest ziet u precies welke mogelijkheden vandaag Delphi-only zijn: de zlib-ng- en zopfli-deflate-entrypoints, libjpeg-compressie en -decompressie, de OpenJPEG JPEG 2000-codec, libtiff met zijn per-compressie-initialiseerders, JBIG2-encoding en -decoding, de Little-CMS-kleurtransformatie-entrypoints, en de AES-primitieven. De ontwerpkeuze achter de stubs weegt zwaarder dan de lijst. Een ontbrekend symbool bij het linken geeft u een muur van undefined references uit een unit die u nooit hebt aangeraakt; een stub die ENotSupportedException gooit geeft u een build die draait, een melding die de reden noemt, en een stacktrace die naar de call site wijst. Het betekent ook dat een Free Pascal-build nooit stilletjes verkeerde bytes produceert waar een Delphi-build de juiste zou leveren. Merk ook het tweede-orde-effect op: onbetrouwbare image-codecs in een geïsoleerd proces draaien is een beslissing die alleen op de Delphi-build rijst, want een Free Pascal-build heeft in de eerste plaats geen native decoder in-process om te sandboxen
Compressie: de eerste regel om te wijzigen is cmNone
Voordat u iets anders port, zet Compression op cmNone. THPDFCompressionMethod biedt precies twee waarden, cmNone en cmFlateDecode, en de tweede loopt rechtstreeks de deflate-entrypoints binnen die in een Free Pascal-build stubs zijn. Verifieer eerst het kernobjectmodel met compressie uit, en beslis daarna wat u verder nodig hebt. Dat is de volgorde die de meegeleverde smoke test gebruikt: een eenpaginig ongecomprimeerd document maken, het herladen, en vaststellen dat het pagina-aantal als één terugkomt. Ongecomprimeerde uitvoer is groter, en het is nog steeds een volkomen geldige 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 belandt op een stub-symbool
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.
Wat gebeurt er met parallel paginarenderen?
Het compileert nog steeds, geeft nog steeds correcte bitmaps terug, en houdt op parallel te zijn. THotPDF.RenderLoadedPagesParallel en THotPDF.RenderLoadedPagesParallelOrdered zijn gebouwd op TThread.CreateAnonymousThread met een inline procedure-closure, die Free Pascal 3.2.2 niet kan uitdrukken, dus de Free Pascal-tak draait een deterministische seriële fallback: hij loopt de pagina-indices in volgorde af, roept RenderLoadedPageToBitmap voor elke aan, en telt de successen. De API-vorm, de retourwaarde en de uitvoerarray zijn onveranderd, wat maakt dat één codebase beide kanten op kan bouwen
var
Bitmaps: THPDFBitmapArray;
Info: THPDFParallelRenderPipelineInfo;
Rendered: Integer;
begin
Rendered := Pdf.RenderLoadedPagesParallel([0, 1, 2, 3], 150, 4,
Bitmaps, Info);
// Delphi: Info.WorkerCount is wat het geheugenbudget toestond
// Free Pascal: Info.WorkerCount is altijd 1, pagina's in indexvolgorde
if Info.WorkerCount = 1 then
LogSerialFallback(Rendered, Info.RequestedWorkerCount);
De fallback is niet stilletjes, en dat is het deel waar u rond kunt ontwerpen. Hij vult THPDFParallelRenderPipelineInfo eerlijk: PageCount uit het verzoek, RequestedWorkerCount als echo van wat u vroeg, WorkerCount op 1, en de voltooide en geleverde aantallen matchend met wat er echt terugkwam. Code die Info al inspecteert om de maat van een voortgangsbalk of een geheugenbudget te bepalen werkt gewoon door en leest de waarheid in plaats van een aanname. Als uw doorvoerplan afhangt van de parallel-render-pipeline en zijn backpressuremodel, is dat plan een Delphi-plan; op Free Pascal budgetteert u de single-threaded kosten van een pagina naar een bitmap renderen maal het pagina-aantal
Welke build moet u eigenlijk uitleveren?
Kies op mogelijkheden, niet op voorkeur. Als uw workflow documentassemblage is, tekst- en vectortekening, formulierinvulling, laden en opslaan, dan dekt de Free Pascal-build op Win64 het, en u valideert met compressie uit voordat u iets aanzet. Als het JPEG-, JPEG 2000-, TIFF- of JBIG2-images raakt, ICC-kleurtransformaties, gecomprimeerde uitvoer, of doorvoer die van veel cores afhangt, blijf voorlopig op Delphi of C++Builder. De grens wordt getrokken door een object-file-ABI en een ontbrekende taalfeature, allebei zichtbaar in de broncode in plaats van begraven in een supportmatrix, en allebei met een benoemde fout failend in plaats van met een verkeerd resultaat
Het Free Pascal- en Lazaruspakket wordt geleverd in dezelfde distributie als de Delphi- en C++Builder-units, dus een licentie dekt beide en u kunt het Lazarus-pad tegen uw eigen documenten testen voordat u eraan commit; de productpagina HotPDF Delphi PDF Component draagt de actuele compilersupportmatrix en de volledige API-referentie