HotXLS, Windows'ta Free Pascal ve Lazarus altında derlenir ve portaj, Object Pascal sözdizimiyle hiç ilgisi olmayan dört karara dayanır: çekirdeği DELPHIUNICODE modunda tutmak, OLE structured-storage interfacelerini elle referans sayılan CORBA interfaceler olarak bildirmek, Win32 AES nesne dosyalarını bir Pascal uygulamasıyla değiştirmek ve kesilmiş bir ZIP'i tam kabul edebilen bir inflate döngüsünü düzeltmek
Olgun bir Delphi kütüphanesini portajlamış herkes bu işin şeklini bilir. Derleyici ilk geçişte neredeyse her şeyi kabul eder. Ardından, temiz derlenen ama yanlış sonuç üreten davranış farklarının uzun kuyruğu gelir ve bir spreadsheet motoru bunlara olağandışı açıktır; çünkü metin kodlamasına, COM structured storage'a, sıkıştırmaya ve kriptografiye tek bir kod yolunda dokunur
Çekirdek neden yalın DELPHI yerine DELPHIUNICODE'de ısrar eder?
Çünkü formül motoru, String ile Char'ın UTF-16 semantiği taşımasına yaslanır ve ANSI alternatifi, dosyaya bir şey ulaşmadan karakterleri kaybettirir. Çekirdeği FPC DELPHI modunda kurmak caziptir; çoğu portajın uzandığı uyumluluk anahtarı odur ve kod derlenir de. Sonra Çince sayfa adlı ya da Kiril etiketli bir çalışma kitabı hesaplama yolundan gidiş-geliş yapar ve yazıcı onları görene dek karakterler çoktan gitmiştir; ortada hiçbir hata yoktur
Mod kütüphane genelinde tekdüze değildir ve bu dağınıklık değil kasıtlılıktır. PNG bayt çözücüsü ile LCL override'ları gerçekten ANSI imzalar ister; çünkü bayt ve widgetset'in kendilerine verdiğiyle iş yaparlar. O unit'ler ayrı bir LX_FPC_ANSI anahtarı açar. Tek kütüphanede iki mod, alternatifin girdisini metin sanan bir bayt çözücüsü olduğunu fark edene kadar kod kokusu gibi duyulur
Sonradan yakalayan bir refik ayrıntı daha var. FPC runtime'ında DELPHIUNICODE, TFormatSettings.DecimalSeparator'ı bir WideChar yapmaz. Unicode ondalık ayracı taşıyan girdi, önce Unicode dizgenin içinde bir ASCII ayracına normalize edilmelidir ve ayracı bekleneni tutmayan her girdi, çözümleyicinin tanımadığı karakterde sessizce kırpılmak yerine reddedilmelidir
program ExportReport;
{$MODE DELPHI}
uses
Interfaces, // önce gelmeli: LCL widgetset'ini ilklendirir
SysUtils, lxHandle; // ve UTF-8 dönüşüm katmanını
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 unit'i isteğe bağlı değildir ve önce gelmek zorundadır. LCL widgetset'ini ve UTF-8 dönüşüm katmanını ilklendiren odur ve HotXLS, fontlar, dosya yolları ya da metin RTL ile LCL sınırını geçtiği anda ikisine de yaslanır. Onu atlayan bir konsol programı derlenir ama her non-ASCII yolda yanlış davranır. Başarılı bir derlemenin burada az şey kanıtlamasının nedeni de budur: portaj, gerçek font adları ve gerçek yollar taşıyan gerçek belgeler tam bir gidiş-dönüş yaptığında ancak kanıtlanabilir biçimde çalışıyordu
Bir sınıf VMT'si bir COM vtable değildir
Free Pascal, bir sınıf VMT'sini bildirim Delphi'nin kabul ettiğine tıpatıp benzese bile Windows'a bir COM interface vtable olarak vermenize izin vermez. Yerleşimler, yanlış slota çağrı üreten şekillerde farklıdır; bu da çağrı noktasıyla ilgisiz bir yerde çökme olarak görünür. Structured storage burada önemlidir; çünkü klasik ikili çalışma kitabı formatı bir OLE compound dosyasıdır ve birini okumak ya da yazmak, Windows storage API'sinin geri çağıracağı ILockBytes'i uygulamak demektir
İşleyen düzen, COM slotları açıkça bildirilmiş ve AddRef ile Release elle yönetilen bir CORBA interface'tir. Bu, bu türler için otomatik referans sayımından vazgeçip yaşam süresinin sorumluluğunu almak demektir; tek bir unit içinde yaşayan bir avuç interface için adil bir takastır. O işin içindeki özgül tuzak QueryInterface'tir: interface pointer döndürmek zorundadır, nesne pointer'ı değil. İkisi de derlenir. Birinin verdiği adresin ilk makine kelimesi bir vtable değildir
FPC'ye özgü bildirimler lxOleInterfaces.inc içinde, FPC kaynak dizininde lxAESBackend.inc ile lxZlibBackend.inc'in yanı başında durur; böylece derleyiciye özgü seçimler motor içinde dağılmak yerine tek bir yerde oturur. Formatın kendisi ve kütüphanenin onda nasıl gezindiği, Pascal'da OLE2 compound dosyaları okuma makalesinde anlatılır
Aynı aileden bir tür ayrıntısı daha var. LargeInt, FPC dalında Int64'e çözümlenmelidir ve Comp'un derleyici sınıflandırması iki araç zinciri arasında o kadar farklıdır ki overload çözümlemesi başka bir adayı seçebilir. Büyük-offset davranışını HGLOBAL akışıyla değil dosya akışıyla sınayın: Windows global bellek akışı 4 GiB ötesindeki seek'lerde kendiliğinden dolanır; oradaki geçen bir test, sizin aritmetiğiniz hakkında hiçbir şey kanıtlamaz
Kendisiyle tutarlı bir AES uygulamasının sakladıkları
Delphi derlemesinin bağladığı Win32 AES nesne dosyaları OMF'dir ve Free Pascal bağlayıcısı onları tüketemez; bu yüzden FPC dalı bunun yerine bir Pascal AES uygulaması kullanır. Delphi, hep bağladığı nesne dosyalarını bağlamaya devam eder; böylece yayımlanmış binary, mevcut müşteriler için değişmeden kalır
Doğrulama zorunluluğu, herhangi bir projeye taşınmaya değer kısımdır. Veriyi şifreleyip aynı uygulamayla yeniden çözmek hiçbir şey kanıtlamaz: anahtar takvimi yanlış, blok sırası yanlış ya da zincirlemesi yanlış bir simetrik algoritma kusursuz biçimde kendisiyle tutarlıdır ve kendi çıktısını her seferinde gidiş-dönüş yapar. Yakalayan tek şey known-answer vektörleridir: anahtar genişletmesini, blok sırasını ve CBC zincirlemesini yayımlanmış değerlerle karşılaştırır. Kendisiyle tutarlı yanlış bir uygulamayı sevk edin ve belirti, bir müşteri dosyayı Excel'de ilk açtığında görünür
Sıkıştırmada ise farklı karakterde bir kusur vardı. Bir Pascal inflate backend'i, sıkıştırılmış girdisinin tamamını tükettikten sonra hâlâ çıktı bekletiyor olabilir; çağıranın, akış sonunu bildirene kadar çağırmaya devam etmesi gerekir. Tükenmiş girdiyi akış sonu saymak son bloğu kırpar. Daha kötüsü, hasarlı bir arşivi sessizce kabul edilen bir arşive çevirir; ZIP end-of-central-directory kaydının doğrulanması makalesindeki sertleştirmenin önlemek için var olduğu hata modu tam olarak budur. Kural şudur: ilerleme yok artı bitmedi, bir kesilme hatasıdır; asla EOF değil
Gerçek saatler yutan iki derleme sistemi tuzağı
LCL arama yolları, FPC paket joker yollarından önce gelmek zorundadır; yoksa Free Vision'ın Menus unit'i, aynı adlı LCL unit'ini gölgeler ve ikisi hakkında da hiçbir şey söylemeyen bir PPU checksum uyuşmazlığı alırsınız. Kurulduktan sonra taşınmış bir Lazarus kurulumu ayrıca fpc.cfg içinde bayat yollar bırakabilir; bu yüzden derleme giriş noktaları, ortamın sunacağını devralmak yerine unit ve binary yollarını açıkça belirtir
İkinci tuzak Pascal'la ilgisizdir. LF satır sonlarıyla yazılmış bir .cmd toplu dosyası, dosya yorumlayıcının okuma tamponu büyüklüğünü aşana kadar çalışır; o noktada call :label, toplu etiketinin var olmadığı iddiasıyla kalır ve hata, sınırın ötesinde duran hangi program varsa onda belirir. Toplu betiği yeniden yazan her aracın CRLF'i geri yazması gerekir. Ve lazbuild --build-all, derlemeden önce paket unit çıktı dizinini temizler; o dizinde park edilmiş bir options dosyası, okunabilmeden silinir: onu dışarıda tutun ve @ yolunun paket dizinine göre çözümlendiğini hatırlayın, çünkü lazbuild derleyiciyi oradan çağırır
// Lazarus grid dışa aktarımı: TGridToXLS Lazarus paketiyle gelir; aynı
// DB-grid dışa aktarım kodu bir LCL uygulamasında da çalışır
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;
Bir derleyici uyarısının değeri
Free Pascal, Delphi'nin bildirmediği ilklendirilmemiş yerel değişkenleri bildirir ve FPC derlemesini çalıştırmak o farkı, hesaplama unit'inde iki gerçek kusura dönüştürdü. Bir işlev, kullanılmadan önce hiç atanmamış bir sayaç değişkenini okudu; öteki, kendilerini hesaplayan kod başka bir dalda çalışmadan önce bir dalda iki koordinat kullandı. Delphi altında ikisi de stack'te tesadüfen ne varsa ona göre davrandı; ki bu, bir makinede tekrarlanıp öbüründe tekrarlanmayan böceğin tanımıdır
Pratik sonuç şu: esas olarak ilk derleyicide sevk edilen bir ürün için bile ikinci derleyiciyi döngüde tutmaya değer. FPC uyarı sınıflarını düzenli aralıklarla taramak, bir Delphi kod tabanına uygulanan ucuz bir statik analiz geçişidir ve hiçbir test süitinin güvenilir biçimde ulaşamadığı bir kusur kategorisini bulur. Bunun içinde yer aldığı daha geniş sürüm matrisi disiplini, çapraz derleyici derleme matrisi makalesinde anlatılır
Windows için Free Pascal ve Lazarus desteği, Delphi ve C++Builder paketlerinin yanında bir Lazarus paketi olarak HotXLS Delphi spreadsheet bileşeni ile birlikte gelir; çatallanma değil aynı kaynak ağacından derlenir. İşin amacı da budur: tek motor, dört araç zinciri ve derleyiciye özgü kararların, tek oturuşta okunabilecek include dosyalarında izole edilmesi