HotPDF se prevede in poganja pod Free Pascal 3.2.2 z Lazarusom in pošten povzetek tega prenosa sta dve povedi. Ustvarjanje dokumentov, nalaganje, shranjevanje, stiskanje, razširjanje, šifriranje in dešifriranje vse delujejo na zaledjih samo Pascal, tako da lahko aplikacija Lazarus proizvede in porabi pravi PDF brez kakršne koli odvisnosti C. Neobvezni domači kodeki slik ne, ker vnaprej zgrajeni objekti Win64 uporabljajo okus COFF, ki ga noben povezovalnik Free Pascal ne more porabiti, zato se na tej orodjarni vstopne točke razrešijo v štube, ki odpovejo zaprto
Od »prevede se« do »deluje« je vzel specifičen nabor popravkov in vsak od njih je past, ki bo našla vsako drugo Delphi kodno bazo, ki se preseljuje na Free Pascal. Vredni so zapisovanja v vrstnem redu, v katerem bolijo
Zakaj dokaz prevajanja enote ne dokazuje ničesar?
Ker lahko Pascalova enota sklicuje simbol, ki nikoli ne bo počel ničesar uporabnega, in še vedno zadovolji prevajalnik. Ob točki, ko se je vseh 113 enot knjižnice gradilo čisto pod Free Pascalom, so obravnavsevalniki vsebnikov arhivov resnično delovali, preverjeno z dimnim testom, ki je odprl CBZ in ga pretvoril v PDF. Utrinjanje obrazcev XFA sploh ni delovalo, ker mora utrinjanje razširiti stisnjen tok paketov /XFA in vstopna točka deflate je bila še štub. Nič v gradbenem izhodu ni razlikovalo teh dveh primerov
Pravilo, ki je iz tega izšlo, je kratko. Pred pisanjem v izdajno opombo, da funkcija deluje na novi orodjarni, napišite izvedbeno sondo, ki vadi funkcijo od konca do konca na tej orodjarni. Pokritost prevajanja je predpogoj, nikoli dokaz. Širša slika tega, kaj prenos pokriva, je v opombah o podpori Win64 Free Pascal in Lazarus
Sprožitev znotraj štuba cdecl ne doseže klicatelja
Ta si zasluži svoj razdelek, ker je simptom tako zavajajoč. Štubne enote izpostavljajo vstopne točke C na način, kot bi ga statična knjižnica, zato štub izgleda takole
// Izgleda razumno. Ni.
function inflate(Strm: Pointer; Flush: Integer): PtrUInt; cdecl;
public name 'inflate';
begin
raise ENotSupportedException.Create('codec unavailable');
end;
Na Free Pascal za Win64 se ta izjema ne širi do klicatelja. Ni ročaja try..except, ki bi ga videl, ker odvijanje čez mejo cdecl, deklarirano na ta način, ne nosi Pascalovega okvira izjem; proces se zaključi z izstopno kodo 217. S strani aplikacije ni napake, ni sporočila in ni vrstice dnevnika, samo program, ki izgine. To je strogo slabše od napačnega odgovora, ker se napačen odgovor lahko obravnava
Vabljiv popravek je narediti štub vračajoč kodo odpovedi namesto tega, in za inflate je to prav, ker ima zlib dobro definirano vračanje napake. Splošno je narobe: štub za jpeg_read_header, ki vrne nič, pove klicatelju, naj nadaljuje s strukturo, ki je nihče ni inicializiral. Trajen popravek je postaviti vrata na Pascalovi vstopni točki in ne znotraj štuba v obliki C, z uporabo katere koli konvencije odpovedi, ki jo ta API že ima
function TryDecodeJPEG(const Data: TBytes; out Bitmap: TBitmap): Boolean;
begin
{$IFDEF FPC}
// Odklonite, preden je štub sploh dosežen, z lastno konvencijo
// odpovedi tega API-ja namesto z izjemo čez cdecl
Bitmap := nil;
Result := False;
Exit;
{$ENDIF}
Result := DecodeJPEGNative(Data, Bitmap);
end;
paszlib ni zlib, razlika pa sta dva razreda dokumentov
Pascalova implementacija deflate, na voljo na Free Pascalu, obravnava dve okvirjanji: ovitek zlib in surovi deflate. Ne obravnava okvirjanja gzip, ki ga zlib izbira skozi vrednosti windowBits od 16 do 31, in ne obravnava načina samodejne zaznave, ki ga vrednosti 32 do 47 izberejo. HotPDF potrebuje oboje. Varna pot uvoza SVG prosi za 31, nalagalnik pa ima lestvico zasilnih rešitev, ki prosi za 47, ko je okvirjanje toka dvoumno. Preskočite katero koli in celotna družina dokumentov preneha odpirati, z napako dekodiranja, ki kaže na tok in ne na manjkajoče okvirjanje
Obstaja druga, ostrejša nezdružljivost. Zapis z_stream, ki ga deklarira paszlib, nima enake razporeditve pomnilnika kot tisti C: njegovo polje msg je kratek niz in ne kazalec, total_in in total_out pa sta 64-bitna, kjer ima C ABI strojne besede. Klicateljev zapis torej ne more biti posredovan naravnost skozi. Delujoča ureditev je obdržati stanje paszlib za kazalcem state, ki ga javni zapis že rezervira, in kopirati javna polja noter in ven okoli vsakega klica. CRC gzip in osmobajtni priklopnik dolžine sta obračunana v isti plasti šima, kar je naravno mesto zanje, ker že lasti odločitev okvirjanja
Posredovanje dinamične matrike netipiziranemu parametru var
To je hrošč, ki je najbolj verjetno pravkar sedeč v vaši kodi. Ko posredujete dinamično matriko netipiziranemu parametru var, je tisto, kar prejme klicani, naslov spremenljivke matrike, ki je naslov kazalca in ne naslov tovora. Torej branje vanjo prepiše samo spremenljivko in kar koli, ki sedi poleg nje
var
FBuffer: TBytes;
begin
SetLength(FBuffer, 65536);
// Napačno: izroči naslov spremenljivke FBuffer
FStream.Read(FBuffer, Length(FBuffer));
// Pravilno: izroči naslov prvega bajta tovora
FStream.Read(FBuffer[0], Length(FBuffer));
end;
Na Delphiju se napačna oblika pogosto zdi delujoča, ker je tisto, kar pokvari, sosednja reža sklada, ki je nič ne bere potem. Na Free Pascal isti vrstici naredi segmentacijsko napako ob prvi uporabi. Tisto, kar jo naredi tako težko opaziti z očmi, je, da statične matrike nimajo takšne težave, ker je spremenljivka statične matrike njen lasten tovor, zato sta obe črkovanji pravilni v isti datoteki, odvisno od deklaracije nekaj sto vrstic stran
Vsebniki ZIP brez System.Zip
Free Pascal nima ustrežnika enote zip RTL, razpoložljiva alternativa pa ima tako drugačno površino API kot tudi brez podpore za podedovano šifriranje, ki ga starejše oblike vsebnikov še vedno uporabljajo, zato se je majhen bralnik znotraj knjižnice izkazal za krajšega kot prilagajanje nanjo. Dve podrobnosti oblike sta stale čas in sta enostavni za pokvariti
Prva je kontrolni bajt glave šifriranja. Njegov dvanajsti bajt je običajno visoki bajt CRC, ko pa je nastavljen bit 3 splošne namenske zastavice, kar pomeni, da velikosti živijo v priključnem opisovalniku podatkov in CRC še ni znan, kontrolni bajt pride namesto tega iz visokega bajta časa spremembe. Implementirajte samo obliko CRC in vsak arhiv, zapisan v tokovnem načinu, zavrne pravilno geslo. Druga je dodatno polje ZIP64: njegova tri 64-bitna polja se pojavijo v fiksnem vrstnem redu, a so zapisana samo, ko je ustrezno 32-bitno polje nasičeno, zato branje na fiksnih odmikih deluje na arhivih, ki ste jih testirali, in odpove na naslednjem. Razčlenite jih položajno proti temu, katera 32-bitna polja so nasičena
Ena priročnost, vredna poznanstva: tok razširjanja Free Pascal vzame drugi argument konstruktorja, ki preskoči glavo zlib, kar je natanko tisto, kar potrebujejo vnosi ZIP, ker shranjujejo surovi deflate. Ta pot sploh ne seže v šim zlib knjižnice, zato ni prizadeta s strani manjkajočega zaledja C
Prosojnost barvnih glifov pod LCL
Branje kanala alfa rastriranega barvnega glifa je ena grafična podrobnost brez neposrednega prevoda. Razred PNG LCL nima dostopnika vrstic prekrivanja, ki bi izpostavil alfo, in dodeljevanje PNG bitni sliki ga zavrže, zato barvni emodži prispe popolnoma neprosojen in se kompozitira s črnim kvadratom za sabo. Delujoča pot je vmesniška slika: ustvarite jo iz PNG, nato berite piksle skozi barvni dostopnik, pri čemer se spomnite, da so njegove komponente 16-bitne in potrebujejo premik navzdol za osem, da postanejo bajti. Ta površina prav tako uporablja naravni vrstni red vrstic od zgoraj navzdol, zato mora biti inverzija Height - 1 - Y, ki jo potrebuje koda vrstic prekrivanja VCL, odstranjena in ne prenesena
Dve opombi gradbenega sistema, preden prijavite hrošča
Polna ponovna gradnja občasno odpove z nedefiniranim simbolom, katerega ime se konča s pripono $crc in šestnajstiško vrednostjo. Ta pripona je izračunana iz tipov parametrov in odpove ujemanju, ko ena gradnja prevede enoto proti dvema različnima različicama vmesnika v istem prehodu. Ponovni zagon gradnje to počisti; podpis ni napačen
Drugič, Free Pascal 3.2.2 nima anonimnih metod, zato kjer koli je knjižnica uporabila zaprtja za povezavo vzporednega cevovoda, vzame gradnja Free Pascal deterministično serijsko zasilno rešitev namesto tega. Izhod je identičen, prepustnost ni; če ste odvisni od vzporednega upodabljanja strani, je to razlog, da za zdaj ostanete na Delphiju, zasnova cevovoda pa je opisana v članku o vzporednem cevovodu upodabljanja. Stanje kodekov slik je drugo mesto, kjer izbira orodjarne spremeni zmožnost in ne samo hitrost, zato naj namestitev Lazarus načrtuje svoje oblike slik ustrezno; trenutna matrika po orodjarnah je na strani produkta HotPDF Delphi PDF component