HotPDF, Free Pascal 3.2.2 ile Lazarus altında derlenir ve çalışır; o portun dürüst özeti iki cümledir. Belge oluşturma, yükleme, kaydetme, sıkıştırma, açma, şifreleme ve şifre çözme, tamamı yalnızca Pascal arka uçları üzerinde çalışır; böylece bir Lazarus uygulaması herhangi bir C bağımlılığı olmadan gerçek PDF üretebilir ve tüketebilir. İsteğe bağlı yerel görüntü kodekleri çalışmaz, çünkü önceden derlenmiş Win64 nesneleri, Free Pascal bağlayıcılarının hiçbirinin tüketemediği bir COFF çeşidi kullanır; dolayısıyla o araç zincirinde giriş noktaları güvenli biçimde başarısız olan stublara çözülür
"Derleniyor"dan "çalışıyor"a ulaşmak belirli bir düzeltmeler kümesine mal oldu ve her biri, Free Pascal'a taşınan herhangi bir başka Delphi kod tabanını da bulacak bir tuzaktır. Acıttıkları sırayla not edilmeye değerler
Bir birimin derlenmesi neden hiçbir şey kanıtlamaz?
Çünkü bir Pascal birimi, hiçbir zaman faydalı bir şey yapmayacak bir sembole atıf yapabilir ve yine de derleyiciyi tatmin eder. 113 kitaplık biriminin tamamı Free Pascal altında temiz derlendiğinde, arşiv kapsayıcı işleyicileri gerçekten çalışıyordu; bir CBZ açıp PDF'e dönüştüren bir duman testi bunu doğruladı. XFA form düzleştirme hiç çalışmadı, çünkü düzleştirmenin sıkıştırılmış /XFA paket akışını açması gerekir ve deflate giriş noktası hâlâ bir stubdu. Derleme çıktısında bu iki durumu ayıran hiçbir şey yoktu
Buradan çıkan kural kısadır. Bir özelliğin yeni bir araç zincirinde çalıştığını sürüm notuna yazmadan önce, o özelliği o araç zincirinde uçtan uca çalıştıran bir çalışma zamanı yoklaması yazın. Derleme kapsamı bir ön koşuldur, asla kanıt değil. Portun neyi kapsadığının daha geniş resmi Free Pascal ve Lazarus Win64 destek notlarında
cdecl stub içindeki bir raise çağırana ulaşmaz
Bu, belirtisi o kadar yanıltıcı ki kendi bölümünü hak eder. Stub birimleri, C giriş noktalarını bir statik kitaplığın açacağı biçimde açar; dolayısıyla bir stub şöyle görünür
// Makul görünüyor. Değil.
function inflate(Strm: Pointer; Flush: Integer): PtrUInt; cdecl;
public name 'inflate';
begin
raise ENotSupportedException.Create('codec unavailable');
end;
Free Pascal Win64 için o istisna çağırana yayılmaz. Onu gören bir try..except işleyicisi yoktur, çünkü bu şekilde bildirilmiş bir cdecl sınırından geriye açılmak Pascal istisna çerçevesini taşımaz; işlem 217 çıkış koduyla sonlanır. Uygulama tarafında hata yoktur, mesaj yoktur, günlük satırı yoktur; sadece kaybolan bir program vardır. Bu, kesinlikle yanlış bir cevaptan daha kötüdür, çünkü yanlış bir cevap ele alınabilir
Baatlı düzeltme, stubun yerine bir başarısızlık kodu döndürmesini sağlamaktır ve inflate için bu doğrudur, çünkü zlib iyi tanımlı bir hata dönüşüne sahiptir. Genel olarak yanlıştır: sıfır döndüren bir jpeg_read_header stubu, çağırana kimsenin başlatmadığı bir yapıyla devam etmesini söyler. Kalıcı düzeltme, C biçimli stubun içinde değil Pascal giriş noktasında kapı koymaktır ve o API'nin zaten sahip olduğu başarısızlık kuralını kullanmaktır
function TryDecodeJPEG(const Data: TBytes; out Bitmap: TBitmap): Boolean;
begin
{$IFDEF FPC}
// Stuba hiç varmadan reddet; cdecl üzerinden istisna yerine bu
// API'nin kendi başarısızlık kuralıyla
Bitmap := nil;
Result := False;
Exit;
{$ENDIF}
Result := DecodeJPEGNative(Data, Bitmap);
end;
paszlib zlib değildir ve fark iki belge sınıfıdır
Free Pascal üzerinde bulunan Pascal deflate uygulaması iki çerçevelemeyi ele alır: zlib sarmalayıcı ve ham deflate. zlib'in 16 ile 31 arası windowBits değerleriyle seçtiği gzip çerçevelemesini ele almaz ve 32 ile 47 arası değerlerin seçtiği otomatik algılama modunu ele almaz. HotPDF her ikisine de ihtiyaç duyar. Güvenli SVG içe aktarma yolu 31 ister ve yükleyicinin, bir akışın çerçevesi belirsiz olduğunda 47 isteyen bir geri düşme merdiveni vardır. Herhangi birini atlamak, bir bütün belge ailesinin açılmasını durdurur; kod çözme hatası da eksik çerçeveyi değil akışı işaret eder
İkinci, daha keskin bir uyumsuzluk vardır. paszlib'in bildirdiği z_stream kaydı, C olanıyla aynı bellek düzenine sahip değildir: msg alanı bir işaretçi yerine kısa dizedir ve total_in ile total_out, C ABI'sinin makine sözcüğü taşıdığı yerde 64 bittir. Dolayısıyla bir çağıran kaydı doğrudan geçirilemez. Çalışan düzen, paszlib durumunu genel kaydın zaten ayırdığı state işaretçisinin ardında tutmak ve genel alanları her çağrı çevresinde içeri dışarı kopyalamaktır. gzip CRC'si ve sekiz baytlık uzunluk sondası da aynı uyum katmanında hesaba katılır; orası onlar için doğal yerdir, çünkü çerçeveleme kararına zaten sahiptir
Türsüz bir var parametresine dinamik dizi geçirmek
Bu, şu anda kodunuzda oturuyor olma ihtimali en yüksek hatadır. Bir dinamik diziyi türsüz bir var parametresine geçirdiğinizde, çağrılanın aldığı şey dizi değişkeninin adresidir; bu bir işaretçinin adresidir, yükün adresi değil. Dolayısıyla içine yapılan bir okuma, değişkenin kendisini ve yanında oturan her şeyi ezer
var
FBuffer: TBytes;
begin
SetLength(FBuffer, 65536);
// Yanlış: FBuffer değişkeninin adresini teslim eder
FStream.Read(FBuffer, Length(FBuffer));
// Doğru: ilk yük baytının adresini teslim eder
FStream.Read(FBuffer[0], Length(FBuffer));
end;
Delphi'de yanlış biçim sık sık çalışıyor görünür, çünkü bozduğu şey sonrasında hiçbir şeyin okumadığı bitişik bir yığın yuvasıdır. Free Pascal'da aynı satır ilk kullanımda segmentasyon hatası verir. Gözle yakalanmasını bu kadar zorlaştıran şey, statik dizilerin böyle bir sorununun olmamasıdır; statik dizi değişkeni kendi yüküdür, dolayısıyla her iki yazım da aynı dosyada birkaç yüz satır ötedeki bildirime bağlı olarak doğrudur
System.Zip olmadan ZIP kapsayıcıları
Free Pascal'ın RTL zip biriminin bir eşdeğeri yoktur ve bulunan alternatifin hem farklı bir API yüzeyi hem de eski kapsayıcı biçimlerinin hâlâ kullandığı eski şifreleme için desteği yoktur; dolayısıyla küçük bir kitaplık içi okuyucu, ona uyum sağlamaktan daha kısa çıktı. İki biçim ayrıntısı zamanına mal oldu ve yanlış yapması kolaydır
İlki şifreleme başlığı denetim baytıdır. On ikinci baytı normalde CRC'nin yüksek baytıdır; ama genel amaçlı bayrak 3. biti ayarlıysa, yani boyutlar sonda bir veri tanımlayıcısında yaşıyorsa ve CRC henüz bilinmiyorsa, denetim baytı bunun yerine değişiklik zamanının yüksek baytından gelir. Yalnızca CRC biçimini uygulayın ve akış modunda yazılan her arşiv doğru bir parolayı reddeder. İkincisi ZIP64 ek alanıdır: üç 64 bitlik alanı sabit bir sırada görünür ama yalnızca karşılık gelen 32 bitlik alan doyduğunda yazılır; dolayısıyla onları sabit ofsetlerden okumak test ettiğiniz arşivlerde çalışır, bir sonrakinde başarısız olur. Hangi 32 bitlik alanların doyduğuna göre konumsal ayrıştırın
Bilmeye değer bir kolaylık: Free Pascal açma akışı, zlib başlığını atlayan ikinci bir kurucu argümanı alır; ZIP girdileri ham deflate sakladığı için tam da ihtiyaç duydukları budur. O yol, kitaplığın zlib uyum katmanına hiç dokunmaz; dolayısıyla eksik C arka ucundan etkilenmez
LCL altında renkli glif saydamlığı
Rasterlenmiş renkli bir glifin alfa kanalını okumak, doğrudan çevirisi olmayan tek grafik ayrıntısıdır. LCL PNG sınıfının alfa açan bir tarama satırı erişicisi yoktur ve bir PNG'yi bir bit eşleme atamak onu atar; dolayısıyla renkli bir emoji tam opak gelir ve arkasında siyah bir kutuyla birleşir. Çalışan yol arayüz görüntüsüdür: onu PNG'den oluşturun, sonra pikselleri renk erişicisi üzerinden okuyun; bileşenlerinin 16 bit olduğunu ve bayta dönüşmek için sekiz kaydırılmaları gerektiğini unutmadan. O yüzey ayrıca doğal yukarıdan aşağıya satır sırası kullanır; dolayısıyla VCL tarama satırı kodunun ihtiyaç duyduğu Height - 1 - Y ters çevirmesi taşınmak yerine kaldırılmalıdır
Hata kaydı açmadan önceki iki derleme sistemi notu
Tam bir yeniden derleme, adı $crc eki ve bir onaltılık değerle biten tanımsız bir sembolle ara sıra başarısız olur. O ek, parametre türlerinden hesaplanır ve bir derleme aynı geçişte bir birimi iki farklı arayüz sürümüne karşı derlediğinde eşleşmez. Derlemeyi yeniden çalıştırmak temizler; imza yanlış değildir
İkincisi, Free Pascal 3.2.2'nin anonim yöntemleri yoktur; dolayısıyla kitaplığın paralel bir hattı bağlamak için kapanış kullandığı her yerde Free Pascal derlemesi bunun yerine belirli bir seri geri düşme alır. Çıktı özdeştir, verim değildir; paralel sayfa çizimine bağımlıysanız bu, şimdilik Delphi'de kalmanın bir nedenidir ve hat tasarımı paralel çizim hattı makalesinde anlatılır. Görüntü kodek durumu, araç zinciri seçiminin yalnızca hızı değil yeteneği değiştirdiği diğer yerdir; dolayısıyla bir Lazarus dağıtımı görüntü biçimlerini ona göre planlamalıdır. Güncel araç zinciri başına matris HotPDF Delphi PDF component ürün sayfasındadır