HotXLS se pod Free Pascal in Lazarus na Windows zgradi, preselitev pa je vzklila na štirih odločitvah, ki nimajo nič s skladnjo Object Pascal: jedro obdržati v načinu DELPHIUNICODE, vmesnike strukturirane shrambe OLE razglasiti kot vmesnike CORBA z ročno vodenim štetjem sklicev, objektne datoteke AES Win32 zamenjati s Pascal implementacijo in popraviti zanko inflate, ki bi lahko sprejela odrezan ZIP kot cel
Vsak, ki je preselil zrelo Delphi knjižnico, pozna obliko tega dela. Prevajalnik ob prvem prehodu sprejme skoraj vse. Sledi dolg rep vedenjskih razlik, ki se čisto prevedejo in proizvedejo napačne rezultate, preglednični motor pa je nanje nenavadno izpostavljen, ker se v eni sami kodni poti dotakne kodiranja besedila, strukturirane shrambe COM, stiskanja in kriptografije
Zakaj jedro vztraja pri DELPHIUNICODE in ne pri navadnem DELPHI?
Ker je motor formul odvisen od tega, da String in Char nosita semantiko UTF-16, alternativi ANSI pa znaki izgubijo, preden karkoli pride do datoteke. Mamljivo je zgraditi jedro v FPC načinu DELPHI, saj je to stikalo združljivosti, po katerem sega večina preselitev, in koda se prevede. Potem delovna knjiga s kitajskimi imeni listov ali ciriličnimi oznakami naredi povratni skozi računsko pot in znaki so izginili, preden jih pisec sploh vidi — brez nobene napake
Način ni povsod enoten čez knjižnico in to je namerno, ne neurejeno. Dekodirnik bajtov PNG in prevali LCL resnično potrebujejo podpise ANSI, ker upravljata z bajti in s tem, kar jima podala gradnikova množica (widgetset). Te enote vklopijo ločeno stikalo LX_FPC_ANSI. Dva načina v eni knjižnici zveni kot zadah, dokler ne opazite, da je alternativa dekodirnik bajtov, ki svoj vhod obravnava kot besedilo
Obstaja še podrobnost v spremstvu, ki ljudi ujame kasneje. DELPHIUNICODE ne naredi TFormatSettings.DecimalSeparator v WideChar v izvajalnem okolju FPC. Vhod, ki nosi decimalno ločilo Unicode, se mora najprej normalizirati na ločilo ASCII znotraj niza Unicode, vsak vhod, katerega ločilo se ne ujema s pričakovanim, pa mora biti zavrnjen in ne tiho odrezan pri znaku, ki ga razčlenjevalnik ni prepoznal
program ExportReport;
{$MODE DELPHI}
uses
Interfaces, // mora priti prvi: inicializira LCL widgetset
SysUtils, lxHandle; // in plast pretvorbe UTF-8
var
Book: TXLSWorkbook;
begin
Book := TXLSWorkbook.Create(nil);
try
Book.LoadFromFile('input.xls');
Book.Sheets[0].AsString[1, 1] := 'Quarterly summary';
Book.SaveToFile('output.xls');
finally
Book.Free;
end;
end.
Enota Interfaces ni neobvezna in mora priti prva. Ona inicializira gradnikovo množico LCL in plast pretvorbe UTF-8, HotXLS pa se zanaša na oboje, takoj ko pisave, poti datotek ali besedilo prečkata mejo med RTL in LCL. Konzolni program, ki jo preskoči, se bo prevedel in se bo slabo vedel na kateri koli ne-ASCII poti. To je tudi razlog, zakaj uspešen prevod tu dokazuje tako malo: preselitev je bila pokazno delujoča šele, ko so resnični dokumenti z resničnimi imeni pisav in resničnimi potmi naredili poln povratni skok
Razredni VMT ni COM vtable
Free Pascal vam ne bo dovolil podati razrednega VMT Windowsom kot vtable vmesnika COM, tudi če deklaracija izgleda identična tisti, ki jo Delphi sprejme. Razporeditvi se razlikujeta na načine, ki proizvedejo klic v napačno mesto, kar se manifestira kot sesutje nekam, nepovezanega z mestom klica. Strukturirana shramba je tu pomembna, ker je klasični binarni format delovne knjige sestavljena datoteka OLE, branje ali pisanje take pa pomeni implementirati ILockBytes, v katere bo shrambni API Windows klical nazaj
Delujoča ureditev je vmesnik CORBA z izrecno razglašenimi COM mesti in ročno vodenima AddRef in Release. To pomeni odreči se samodejnemu štetju sklicev za te tipe in prevzeti odgovornost za življenjsko dobo — poštena menjava za peščico vmesnikov, ki živijo znotraj ene enote. Določena past znotraj tega dela je QueryInterface: mora vrniti kazalec na vmesnik, ne kazalca na objekt. Oboje se prevede. En od njiju poda Windowsom naslov, katerega prva strojna beseda ni vtable
Deklaracije, specifične za FPC, živijo v lxOleInterfaces.inc, poleg lxAESBackend.inc in lxZlibBackend.inc v izvornem imeniku FPC, tako da izbire, specifične za prevajalnik, sedejo na enem mestu in niso raztresene čez motor. Sam format in kako se vanj krmarita knjižnici sta opisana v brananju sestavljenih datotek OLE2 v Pascalu
Še ena tipna podrobnost sodi v isto družino. LargeInt se mora v veji FPC razrešiti v Int64, razvrstitev tipa Comp s strani prevajalnika pa se med toolchainoma dovolj razlikuje, da lahko razreševanje preobremenitev izbere drugega kandidata. Vedenje velikih odmikov testirajte s tokom datoteke in ne s tokom HGLOBAL: tok globalnega pomnilnika Windows se sam ovije pri iskanjih čez 4 GiB, tako da uspešen test tam ne dokaže nič o vaši lastni aritmetiki
Kaj skriva samoskladna implementacija AES
Objektne datoteke AES Win32, ki jih povezuje gradnja Delphi, so OMF in jih povezovalnik Free Pascal ne more pogoltniti, zato veja FPC namesto njih uporablja Pascal implementacijo AES. Delphi še naprej povezuje objektne datoteke, ki jih je vedno, kar izdano binarko obdrži nespremenjeno za obstoječe stranke
Zahteva po preverjanju je del, ki ga vredi odnesti v vsak projekt. Šifriranje podatkov in ponovno dešifriranje z isto implementacijo ne dokaže nič: simetrični algoritem z napačnim razporedom ključev, napačnim vrstnim redom blokov ali napačnim veriženjem je popolnoma samoskladen in bo vsakič naredil povratni skok svojega izhoda. Ujamejo ga le vektorji znanih odgovorov, ki preverijo širitev ključev, vrstni red blokov in veriženje CBC proti objavljenim vrednostim. Pošljite samoskladno napačno implementacijo in simptom se pokaže prvič, ko stranka odpre datoteko v Excelu
Stiskanje je imelo pomanjkljivost drugega značaja. Zaledje inflate v Pascalu lahko še ima izhod v čakanju, potem ko je porabil ves stisnjeni vhod, zato mora klicatelj klicati naprej, dokler tok ne sporoči svojega konca. Obravnava izčrpanega vhoda kot konec toka odreže zadnji blok. Slabše — poškodovan arhiv spremeni v tiho sprejetega, kar je natanko način odpovedi, ki mu je utrjevanje v validaciji zapisa ZIP end-of-central-directory namenjeno preprečiti. Pravilo je: brez napredka plus ni končano je napaka odrezanja in nikoli EOF
Dve pasti gradbenega sistema, ki staneta prave ure
Iskalne poti LCL morajo iti pred nadomestnimi potmi paketov FPC, sicer enota Menus Free Vision zasenči enoto LCL z istim imenom in dobite neskladje kontrolne vsote PPU, ki o čemer koli od obeh ne pove nič. Namestitev Lazarus, premaknjena po namestitvi, lahko tudi pusti zastarele poti v fpc.cfg, zato vstopne točke gradnje izrecno navedejo poti enot in binarnih datotek namesto da bi podedovale, kar okolje ponudi
Druga past nima nič s Pascalom. Paketna datoteka .cmd, zapisana s konci vrstic LF, deluje, dokler datoteka ne zraste čez velikost bralnega medpomnilnika tolmača — takrat call :label spodleti s trditvijo, da paketna oznaka ne obstaja, spodletel pa se pokaže pri katerem koli programu, ki slučajno sede čez mejo. Vsako orodje, ki prepiše paketni skript, mora zapisati CRLF nazaj. In lazbuild --build-all počisti izhodni imenik enot paketa, preden prevaja, tako da je datoteka možnosti, parkirana v tem imeniku, izbrisana, preden jo je mogoče prebrati: hranite jo zunaj in pomnite, da se pot @ razreši relativno na imenik paketa, ker lazbuild prevajalnik prikliče od tam
// Izvoz mreže Lazarus: TGridToXLS pride z paketom Lazarus, zato ista
// koda izvoza DB-grid deluje v aplikaciji LCL
var
Exporter: TGridToXLS;
begin
Exporter := TGridToXLS.Create(nil);
try
Exporter.DBGrid := GridOrders;
Exporter.WorksheetName := 'Orders';
Exporter.ExportHeader := True;
Exporter.SetColumnsWidth := True;
Exporter.ExportDBGrid;
Exporter.SaveAs('orders.xls');
finally
Exporter.Free;
end;
end;
Kaj je vredno opozorilo prevajalnika
Free Pascal sporoča neinicializirane krajevne spremenljivke, ki jih Delphi ne, in zagon gradnje FPC je to razliko spremenil v dve resnični pomanjkljivosti v računski enoti. Ena funkcija je brala številsko spremenljivko, ki nikoli ni bila dodeljena pred uporabo, druga pa je v eni veji uporabila dve koordinati, preden je koda, ki ju je izračunala, tekla v drugi veji. Pod Delphi sta se obe vedli po tistem, kar je sklad slučajno držal — to je definicija hrošča, ki se reproducira na enem računalniku in ne na drugem
Praktični sklep je, da je drugi prevajalnik vreden ostati v zanki, tudi za izdelek, ki se primarno pošilja na prvem. Občasno preleteti razrede opozoril FPC je poceni prehod statične analize čez Delphi kodno bazo in najde kategorijo pomanjkljivosti, do katere nobena testna zbirka zanesljivo ne pride. Širša disciplina matrike verzij, v kateri to sede, je opisana v matriki gradenj čez prevajalnike
Podpora Free Pascal in Lazarus za Windows pride z HotXLS Delphi spreadsheet component kot paket Lazarus ob paketih Delphi in C++Builder, zgrajen iz istega izvornega drevesa in ne iz vilice. To je poanta vaje: en motor, štirje toolchaini in odločitve, specifične za prevajalnik, izolirane v vključitvenih datotekah, kjer jih je mogoče prebrati v enem sedenju