HotXLS statoosi su Free Pascal ir Lazarus Windows sistemoje, ir pernešimas priklausė nuo keturių sprendimų, neturinčių nieko bendra su Object Pascal sintakse: laikyti šerdį DELPHIUNICODE režime, deklaruoti OLE struktūrinės saugyklos sąsajas kaip CORBA sąsajas su rankomis valdomu nuorodų skaičiavimu, pakeisti Win32 AES objektinius failus Pascal realizacija, ir sutvarkyti inflate ciklą, kuris galėjo priimti nukirptą ZIP kaip pilną
Kas bet kada pernešė brandžią Delphi biblioteką, tas žino šio darbo formą. Kompiliatorius priima beveik viską pirmu perėjimu. Po to seka ilga elgesio skirtumų uodega, kurie kompiliuojasi švariai ir duoda neteisingus rezultatus, o skaičiuoklės variklis prie jų neįprastai atviras, nes jis liečia teksto kodavimą, COM struktūrinę saugyklą, kompresiją ir kriptografiją viename kodo kelyje
Kodėl šerdis reikalauja DELPHIUNICODE, o ne paprasto DELPHI?
Nes formulės variklis priklauso nuo String ir Char, nešančių UTF-16 semantiką, o ANSI alternatyva praranda simbolius dar prieš ką nors pasiekiant failą. Pagunda statyti šerdį FPC DELPHI režime yra didelė, nes tai suderinamumo jungiklis, kurį dauguma pernešimų ir renkasi, ir kodas kompiliuojasi. Tada darbo knyga su kinietiškais lapų pavadinimais ar kirilicos etiketėmis praeina pro skaičiavimo kelią atgal ir pirmyn, ir simbolių nebėra, kai rašytojas juos mato, be jokios klaidos
Režimas nėra vienodas visoje bibliotekoje, ir tai sąmoninga, o ne netvarkinga. PNG baitų dekoduotojui ir LCL perrašymams tikrai reikia ANSI parašų, nes jie elgiasi baitais ir tuo, ką widgetset jiems atiduoda. Tie moduliai įjungia atskirą LX_FPC_ANSI jungiklį. Du režimai vienoje bibliotekoje skamba kaip code smell, kol nepastebi, kad alternatyva yra baitų dekoduotojas, traktuojantis savo įvestį kaip tekstą
Yra lydraštė detalė, kuri pagauna žmones vėliau. DELPHIUNICODE nepadaro TFormatSettings.DecimalSeparator WideChar FPC runtime viduje. Įvestis, nešanti Unicode dešimtainį skyriklį, turi būti normalizuota į ASCII skyriklį Unicode eilutės viduje pirmiausia, o bet kokia įvestis, kurios skyriklis nesutampa su laukiamuoju, turi būti atmetama, o ne tyliai nukerpama ties simboliu, kurio analizatorius neatpažino
program ExportReport;
{$MODE DELPHI}
uses
Interfaces, // turi ateiti pirmas: inicializuoja LCL widgetset
SysUtils, lxHandle; // ir UTF-8 konversijos sluoksnį
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.
Interfaces modulis nėra pasirinktinas ir jis turi ateiti pirmas. Jis inicializuoja LCL widgetset ir UTF-8 konversijos sluoksnį, o HotXLS remiasi abiem, kai tik šriftai, failų keliai ar tekstas kerta RTL ir LCL ribą. Konsolė programa, praleidusi jį, kompiliuosis ir elgsis blogai bet kuriame ne ASCII kelyje. Tai ir priežastis, kodėl sėkminga kompiliacija čia įrodo tiek mažai: pernešimas buvo įrodytai veikiantis tik tada, kai tikri dokumentai su tikrais šriftų vardais ir tikrais keliais padarė pilną ratą atgal ir pirmyn
Klasės VMT nėra COM vtable
Free Pascal neleis jums atiduoti klasės VMT Windows kaip COM sąsajos vtable, net kai deklaracija atrodo identiška tai, kurią priima Delphi. Išdėstymai skiriasi taip, kad atsiranda iškvietimas į neteisingą lizdą, kas pasireiškia kaip užstrigimas kažkur nesusijusiame su iškvietimo vieta. Struktūrinė saugykla čia svarbi, nes klasikinis dvinarinis darbo knygos formatas yra OLE jungtinis failas, ir tokio skaitymas ar rašymas reiškia ILockBytes realizavimą, į kurį Windows saugyklos API atšauks
Darbinis sutvarkymas yra CORBA sąsaja su aiškiai deklaruotais COM lizdais ir rankomis valdomais AddRef ir Release. Tai reiškia atsisakyti automatinio nuorodų skaičiavimo šiems tipams ir prisiimti atsakomybę už gyvavimo laiką, kas yra sąžiningas mainas saujai sąsajų, gyvenančių viename modulyje. Konkretūs šio darbo spąstai yra QueryInterface: jis turi grąžinti sąsajos rodyklę, o ne objekto rodyklę. Abu kompiliuojasi. Vienas iš jų atiduoda Windows adresą, kurio pirmasis mašininis žodis nėra vtable
FPC specifinės deklaracijos gyvena lxOleInterfaces.inc, greta lxAESBackend.inc ir lxZlibBackend.inc FPC šaltinių kataloge, tad kompiliatoriui specifiniai pasirinkimai sėdi vienoje vietoje, o ne išmėtyti per variklį. Pats formatas ir kaip biblioteka juo naviguoja aprašyti straipsnyje OLE2 jungtinių failų skaitymas Pascal
Dar viena tipo detalė priklauso tai pačiai šeimai. LargeInt turi išsiskirti į Int64 FPC šakoje, ir kompiliatoriaus Comp klasifikacija skiriasi pakankamai tarp dviejų įrankių grandinių, kad perkrovų atranka gali pasirinkti kitą kandidatą. Didelių poslinkių elgesį tikrinkite failų srautu, o ne HGLOBAL srautu: Windows globalios atminties srautas pats apsiverčia pozicionuojant už 4 GiB, tad praeinantis testas ten nieko neįrodo apie jūsų pačių aritmetiką
Ką slepia savaime suderinama AES realizacija
Win32 AES objektiniai failai, kuriuos susieja Delphi versija, yra OMF, ir Free Pascal linkeris jų suvartoti negali, tad FPC šaka naudoja Pascal AES realizaciją vietoj. Delphi toliau susieja objektinius failus, kuriuos visada susiedavo, kas laiko išleistą dvinarinį failą nepakitusį esamiems klientams
Patikros reikalavimas yra dalis, verta nešti į bet kurį projektą. Duomenų užšifravimas ir pakartotinis iššifravimas ta pačia realizacija neįrodo nieko: simetrinis algoritmas su neteisingu rakto grafiku, neteisinga blokų tvarka ar neteisinga grandine yra tobulai savaime suderinamas ir kas kartą praleis savo paties išvestį pro ratą. Tik žinomų atsakymų vektoriai tai pagauna, tikrindami rakto išplėtimą, blokų tvarką ir CBC grandinę prieš paskelbtas reikšmes. Išleiskite savaime suderinamą neteisingą realizaciją, ir simptomas pasirodys pirmą kartą, kai klientas atvers failą Excel
Kompresija turėjo kitokio charakterio defektą. Pascal inflate posistemė gali vis dar turėti išvesties, laukiančios išdavimo, sunaudojusi visą savo suspaustą įvestį, tad kvietėjas turi kviesdamas likti, kol srautas praneša savo galą. Išsekusios įvesties traktavimas kaip srauto galas nukerpa paskutinį bloką. Blogiau – tai pavercia pažeistą archyvą į tyliai priimtą, kas yra tiksliai tas nesėkmės režimas, kurio užkirsti kelią egzistuoja sukietėjimas straipsnyje ZIP end-of-central-directory įrašo patikrinimas. Taisyklė tokia: jokios pažangos plius nebaigta yra nukirpimo klaida, niekada ne EOF
Du statymo sistemos spąstai, kainavę tikrų valandų
LCL paieškos keliai turi eiti priekyje FPC paketų pakaitos kelių, kitaip Free Vision Menus modulis uždengia LCL modulį to paties vardo, ir jūs gaunate PPU kontrolinės sumos nesutapimą, apie kurį nesako nieko nė vienas. Lazarus diegimas, perkeltas po įdiegimo, taip pat gali palikti pasenęs kelius fpc.cfg, tad statymo įėjimo taškai nurodo modulių ir dvinarinius kelius aiškiai, vietoj to, kad paveldėtų ką bepasiūlo aplinka
Antrasis spąstai neturi nieko bendra su Pascal. .cmd paketinis failas, parašytas su LF eilučių pabaigomis, veikia, kol failas išauga už interpretatoriaus skaitymo buferio dydžio, kur call :label nepajėgia teigdamas, kad paketinės etikės nėra, ir nesėkmė pasirodo ties ta programa, kuri atsitiktinai sėdi už ribos. Bet koks įrankis, perrašantis paketinį scenarijų, turi rašyti CRLF atgal. Ir lazbuild --build-all išvalo paketo modulių išvesties katalogą prieš kompiliuodamas, tad parinkčių failas, pastatytas tame kataloge, ištrinamas, kol spėja būti perskaitytas: laikykite jį užapus, ir prisiminkite, kad @ kelias išsiskiria santykinai paketo katalogui, nes lazbuild iškviečia kompiliatorių iš ten
// Lazarus tinklelio eksportas: TGridToXLS keliauja su Lazarus paketu, tad
// tas pats DB-tinklelio eksporto kodas veikia LCL programoje
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;
Ką verta kompiliatoriaus įspėjimas
Free Pascal praneša neinicializuotus vietinius kintamuosius, kurių Delphi nepraneša, ir FPC versijos paleidimas pavertė tą skirtumą dviem tikrais defektais skaičiavimo modulyje. Viena funkcija skaitė skaičiaus kintamąjį, niekada nepriskirtą prieš naudojimą, o kita naudojo dvi koordinates vienoje šakoje prieš kodą, kuris jas perskaičiavo, bėgantį kitoje šakoje. Po Delphi abu elgėsi pagal tai, ką atsitiktinai laikė stekas, kas yra apibrėžimas klaidai, atsikeliančiai viename kompiuteryje ir ne kitoje
Praktinė išvada ta, kad antrasis kompiliatorius vertas likti cikle net produktui, išleidžiamam pirmiausia pirmuoju. FPC įspėjimų klasių skenavimas periodiškai yra pigus statinės analizės perėjimas per Delphi kodų bazę, ir jis randa defektų kategoriją, kurios joks testų rinkinys patikimai nepasiekia. Platesnė versijų matricos drausmė, kurioje tai sėdi, aprašyta straipsnyje kryžminių kompiliatorių statymo matrica
Free Pascal ir Lazarus palaikymas Windows keliauja su HotXLS Delphi skaičiuoklės komponentu kaip Lazarus paketas greta Delphi ir C++Builder paketų, kuriamas iš to paties šaltinių medžio, o ne atšakos. Tam ir buvo ši pratyba: vienas variklis, keturios įrankių grandinės, ir kompiliatoriui specifiniai sprendimai izoliuoti include failuose, kuriuos galima perskaityti vienu sėdimu