A HotPDF Free Pascal 3.2.2 alatt fordul és fut Lazarusszal, és a portolás őszinte összefoglalása két mondat. A dokumentumlétrehozás, betöltés, mentés, tömörítés, kitömörítés, titkosítás és visszafejtés mind kizárólag Pascal backendeken működik, tehát egy Lazarus alkalmazás C függőség nélkül állíthat elő és fogyaszthat valós PDF-et. Az opcionális natív képkodekek nem, mert az előre lefordított Win64 objektumok olyan COFF ízt használnak, amelyet a Free Pascal két linkere egyike sem tud fogyasztani, tehát azon az eszközláncon a belépési pontok olyan csonkokká oldódnak fel, amelyek zártan hibáznak
A „fordul” állapottól a „működik” állapotig egy meghatározott javításkészlet vezetett, és mindegyik olyan csapda, amely bármely más, Free Pascalra költöző Delphi kódbázist megtalál. Megéri őket lejegyezni abban a sorrendben, ahogyan fájtak
Miért nem bizonyít semmit, hogy egy egység lefordul?
Mert egy Pascal egység hivatkozhat olyan szimbólumra, amely soha nem tesz semmi hasznosat, és mégis kielégíti a fordítót. Abban a pillanatban, amikor mind a 113 függvénytári egység tisztán lefordult Free Pascal alatt, az archívumtároló kezelők valóban működtek, amelyet egy füstteszt igazolt, amely egy CBZ-t nyitott meg, és PDF-be alakított. Az XFA űrlaplapítás egyáltalán nem működött, mert a lapításnak ki kell tömörítenie a tömörített /XFA csomagfolyamot, és a deflate belépési pont még csonk volt. Semmi a build kimenetében nem különböztette meg a két esetet
A belőle származó szabály rövid. Mielőtt kiadási megjegyzésbe írja, hogy egy funkció működik egy új eszközláncon, írjon futásidejű szondát, amely a funkciót végponttól végpontig gyakorolja azon az eszközláncon. A fordítási lefedettség előfeltétel, soha nem bizonyíték. A portolás által lefedett szélesebb képet a Free Pascal és Lazarus Win64 támogatási jegyzetek adják
Egy cdecl csonkon belüli dobás nem jut el a hívóig
Ez külön szakaszt érdemel, mert a tünet annyira félrevezető. A csonk egységek úgy tesznek ki C belépési pontokat, ahogyan egy statikus függvénytár tenné, tehát egy csonk így néz ki
// Ésszerűnek látszik. Nem az.
function inflate(Strm: Pointer; Flush: Integer): PtrUInt; cdecl;
public name 'inflate';
begin
raise ENotSupportedException.Create('codec unavailable');
end;
Free Pascal alatt Win64-re ez a kivétel nem jut el a hívóig. Nincs olyan try..except kezelő, amely meglátná, mert az így deklarált cdecl határon átívelő lefejtés nem viszi magával a Pascal kivételkeretét; a folyamat 217-es kilépési kóddal ér véget. Az alkalmazás felől nincs hiba, nincs üzenet, nincs naplósor, csak egy program, amely eltűnik. Ez szigorúan rosszabb, mint egy rossz válasz, mert a rossz válasz kezelhető
A kísértő javítás az, hogy a csonk hibakódot adjon vissza helyette, és az inflate esetében ez helyes, mert a zlib jól definiált hibavisszatéréssel rendelkezik. Általában téves: egy olyan jpeg_read_header csonk, amely nullát ad vissza, azt mondja a hívónak, hogy folytassa egy olyan struktúrával, amelyet senki nem inicializált. A tartós javítás az, hogy a Pascal belépési ponton kapuzzon, nem a C-alakú csonkon belül, az adott API meglévő hibakonvencióját használva
function TryDecodeJPEG(const Data: TBytes; out Bitmap: TBitmap): Boolean;
begin
{$IFDEF FPC}
// Utasítsa el még a csonk elérése előtt, ennek az API-nak a saját
// hibakonvenciójával, nem pedig cdecl-en átkelő kivétellel
Bitmap := nil;
Result := False;
Exit;
{$ENDIF}
Result := DecodeJPEGNative(Data, Bitmap);
end;
A paszlib nem zlib, és a különbség két dokumentumosztályt érint
A Free Pascallen elérhető Pascal deflate implementáció két keretezést kezel: a zlib burkolót és a nyers deflatet. Nem kezeli a gzip keretezést, amelyet a zlib a windowBits 16 és 31 közötti értékeivel választ, és nem kezeli az automatikus észlelési módot sem, amelyet a 32 és 47 közötti értékek választanak. A HotPDF-nek mindkettő kell. A biztonságos SVG import út 31-et kér, és a betöltőnek olyan tartaléklétrája van, amely 47-et kér, amikor egy folyam keretezése kétértelmű. Bármelyik kihagyása esetén egy egész dokumentumcsalád áll le a nyitással, olyan dekódolási hibával, amely a folyamra mutat, nem a hiányzó keretezésre
Van egy második, élesebb összeférhetetlenség is. A paszlib által deklarált z_stream rekord nem azonos memóriaelrendezésű a C-vel: a msg mezője rövid karakterlánc, nem pointer, és a total_in és total_out 64 bites ott, ahol a C ABI gépi szavakat használ. Egy hívói rekord tehát nem adható át egyenesen. A működő megoldás az, hogy a paszlib állapotot a nyilvános rekord által már fenntartott state pointer mögött tartják, és a nyilvános mezőket minden hívás körül ki-be másolják. A gzip CRC és a nyolc bájtos hosszlábjegyzet ugyanabban a shim rétegben kerül elszámolásra, amely a természetes helyük, mert az már birtokolja a keretezési döntést
Dinamikus tömb átadása típus nélküli var paraméternek
Ez az a hiba, amely a legvalószínűbben éppen most ül az Ön kódjában. Amikor dinamikus tömböt ad át típus nélküli var paraméternek, amit a hívott kap, az a tömbváltozó címe, amely egy pointer címe, nem a hasznos teher címe. Tehát beleolvasás felülírja magát a változót és mindent, ami mellette ül
var
FBuffer: TBytes;
begin
SetLength(FBuffer, 65536);
// Rossz: az FBuffer változó címét adja át
FStream.Read(FBuffer, Length(FBuffer));
// Helyes: az első hasznos teher bájtjának címét adja át
FStream.Read(FBuffer[0], Length(FBuffer));
end;
Delphi alatt a rossz forma gyakran működőnek látszik, mert az, amit megrongál, egy szomszédos veremhely, amelyet utána semmi nem olvas. Free Pascal alatt ugyanaz a sor első használatkor szegmenshibát okoz. Ami megnehezíti a szemmel való észrevételt, az, hogy a statikus tömböknek nincs ilyen problémájuk, mert egy statikus tömbváltozó saját hasznos tehere, tehát mindkét írásmód helyes ugyanabban a fájlban attól függően, hogy néhány száz sorral odébb milyen a deklaráció
ZIP tárolók System.Zip nélkül
A Free Pascalnak nincs az RTL zip egységének megfelelője, és az elérhető alternatívának is más az API felülete, és nincs támogatása az örökölt titkosításhoz, amelyet régebbi tárolóformátumok még használnak, tehát egy kis, függvénytáron belüli olvasó rövidebbnek bizonyult, mint ahhoz alkalmazkodni. Két formátumrészlet időbe került, és könnyű elrontani
Az első a titkosítási fejléc ellenőrzőbájtja. Tizenkettedik bájtja normálisan a CRC felső bájtja, de amikor az általános célú jelző 3. bitje be van állítva, ami azt jelenti, hogy a méretek egy záró adatleíróban élnek, és a CRC még nem ismert, az ellenőrzőbájt a módosítási idő felső bájtjából jön. Csak a CRC formát implementálva minden streaming módban írt archívum elutasít egy helyes jelszót. A második a ZIP64 extra mező: a három 64 bites mezője rögzített sorrendben jelenik meg, de csak akkor íródnak, amikor a megfelelő 32 bites mező telített, tehát rögzített offseteken olvasva azok a tesztelt archívumokon működnek, és a következőn megbuknak. Elemezze őket pozicionálisan aszerint, hogy mely 32 bites mezők telítettek
Egy kényelem, amelyet érdemes ismerni: a Free Pascal kitömörítési folyamának második konstruktorargumentuma átugorja a zlib fejlécet, ami pontosan az, amire a ZIP bejegyzéseknek szükségük van, mert nyers deflatet tárolnak. Az az út egyáltalán nem érinti a függvénytár zlib shimét, tehát nem érintett a hiányzó C backendben
Színes glífa átlátszóság az LCL alatt
Egy raszterizált színes glífa alfa csatornájának olvasása az egyetlen grafikai részlet, amelynek nincs közvetlen fordítása. Az LCL PNG osztályának nincs pásztázásvonal-elérője, amely az alfát kitenné, és egy PNG bittérképhez rendelése eldobja azt, tehát egy színes emoji teljesen átlátszatlanul érkezik, és mögötte fekete dobozzal kompozitálódik. A működő út az interfészkép: hozza létre a PNG-ből, majd olvassa a pixeleket a színelérőn át, emlékezve arra, hogy annak komponensei 16 bitesek, és nyolccal lefelé kell őket tolni, hogy bájtok legyenek. Az a felület természetes felülről lefelé sorsort is használ, tehát a Height - 1 - Y inverziót, amelyre a VCL pásztázásvonalkódja szüksége van, el kell távolítani, nem portolni
Két buildrendszeres megjegyzés, mielőtt hibát jelentene
Egy teljes újrafordítás néha megbukik egy meghatározatlan szimbólummal, amelynek neve $crc utótagban végződik egy hexadecimális értékkel. Az az utótag a paramétertípusokból számolódik, és nem talál el, amikor egy build ugyanabban a menetben két különböző interfészverzióval fordít egy egységet. A build újbóli futtatása tisztázza; a szignatúra nem téves
Másodszor, a Free Pascal 3.2.2 nem rendelkezik névtelen metódusokkal, tehát mindenhol, ahol a függvénytár closure-öket használt egy párhuzamos vezeték bekötésére, a Free Pascal build determinisztikus soros tartalékot használ helyette. A kimenet azonos, az átbocsátás nem; ha párhuzamos oldalrendereléstől függ, az most egy ok maradni a Delphi mellett, és a vezetéktervet a párhuzamos rendervezeték cikk írja le. A képkodek-helyzet a másik hely, ahol az eszközláncválasztás képességet változtat, nem csupán sebességet, tehát egy Lazarus telepítésnek ennek megfelelően kell terveznie a képformátumait; az aktuális eszközlánconkénti mátrix a HotPDF Delphi PDF component terméklapon található