Artykuł techniczny

PDFlibPas: DLL, ActiveX, and Dylib integration in Delphi

losLab PDF Library zapewnia zespołom Delphi i C++Builder silnik PDF z dostępnym kodem źródłowym dla przepływów desktopowych, serwerowych, DLL, ActiveX i Dylib, z wbudowanymi kontrolami PDF/A i PDF/UA, podpisami PAdES oraz wyborem renderera bez wysyłania dokumentów do zewnętrznej usługi PDF.

Ten artykuł jest przeznaczony dla teams exposing PDF functionality across Delphi, C++Builder, scripting, legacy automation, or cross-platform components. Traktuje DLL, ActiveX, and Dylib integration jako produkcyjną inżynierię dokumentów, a nie pojedyncze wywołanie komponentu.

Praktyczne ryzyko polega na tym, że native integration bugs often appear as memory corruption, string encoding issues, bitness mismatches, or exception-boundary failures rather than clear PDF errors. Dlatego przepływ wymaga spisanego kontraktu, obserwowalnej diagnostyki i realistycznych plików regresyjnych.

Decyzje architektoniczne

Define a binary contract before feature code. calling convention, bitness, thread model, and supported host languages / string encoding, path encoding, stream ownership, and buffer lifetime rules

  • calling convention, bitness, thread model, and supported host languages
  • string encoding, path encoding, stream ownership, and buffer lifetime rules
  • error reporting style, exception translation, and diagnostic callback behavior
  • deployment layout, dependency versioning, registration, and update policy

Przebieg implementacji

Keep ownership and errors explicit at the boundary. Poniższa kolejność zachowuje czytelność przepływu pracy dla zespołów Delphi i C++Builder.

  1. publish a minimal binary contract before wrapping high-level PDF operations
  2. return explicit handles or result objects rather than sharing unmanaged pointers
  3. translate exceptions into stable error codes and diagnostic messages
  4. validate bitness and dependency versions during initialization
  5. ship sample calls that exercise Unicode paths, large buffers, and failure paths

Dowody walidacji

Integration evidence for support cases. Zachowaj te pola wraz z wynikiem lub rekordem wsparcia.

  • module version, host process bitness, calling convention, and dependency path
  • function name, input sizes, output buffer ownership, and returned status code
  • encoded path or string policy used for the call
  • diagnostic trace that does not cross memory ownership boundaries unsafely

The PDF API is only half of the contract

A DLL, ActiveX, or Dylib layer needs stable calling conventions, buffer ownership rules, string encoding, version reporting, error codes, and deployment checks. Treating it as a thin wrapper without those rules makes support difficult.

Decision table for DLL, ActiveX, and Dylib integration

A decision table keeps product ownership visible when the same workflow is reused by a desktop tool, service job, and support utility.

DecisionEngineering reasonEvidence
calling convention, bitness, thread model, and supported host languagespublish a minimal binary contract before wrapping high-level PDF operationsmodule version, host process bitness, calling convention, and dependency path
string encoding, path encoding, stream ownership, and buffer lifetime rulesreturn explicit handles or result objects rather than sharing unmanaged pointersfunction name, input sizes, output buffer ownership, and returned status code
error reporting style, exception translation, and diagnostic callback behaviortranslate exceptions into stable error codes and diagnostic messagesencoded path or string policy used for the call

Notatki przeglądu inżynierskiego dla DLL, ActiveX, and Dylib integration

Użyj tych notatek przeglądu, aby upewnić się, że funkcja wyszła poza demonstrację i da się ją obronić podczas wydania, wsparcia i eskalacji klienta.

  • Decyzja: calling convention, bitness, thread model, and supported host languages. Punkt nacisku implementacji: return explicit handles or result objects rather than sharing unmanaged pointers. Dowody akceptacji: encoded path or string policy used for the call. Wyzwalacz regresji: uncaught native exceptions can terminate hosts that cannot inspect Delphi state
  • Decyzja: string encoding, path encoding, stream ownership, and buffer lifetime rules. Punkt nacisku implementacji: translate exceptions into stable error codes and diagnostic messages. Dowody akceptacji: diagnostic trace that does not cross memory ownership boundaries unsafely. Wyzwalacz regresji: ANSI paths may work in tests and fail for customer names or localized folders
  • Decyzja: error reporting style, exception translation, and diagnostic callback behavior. Punkt nacisku implementacji: validate bitness and dependency versions during initialization. Dowody akceptacji: module version, host process bitness, calling convention, and dependency path. Wyzwalacz regresji: ActiveX registration can succeed for one bitness and fail for another host
  • Decyzja: deployment layout, dependency versioning, registration, and update policy. Punkt nacisku implementacji: ship sample calls that exercise Unicode paths, large buffers, and failure paths. Dowody akceptacji: function name, input sizes, output buffer ownership, and returned status code. Wyzwalacz regresji: callbacks must not outlive buffers owned by the caller
  • Decyzja: calling convention, bitness, thread model, and supported host languages. Punkt nacisku implementacji: publish a minimal binary contract before wrapping high-level PDF operations. Dowody akceptacji: encoded path or string policy used for the call. Wyzwalacz regresji: uncaught native exceptions can terminate hosts that cannot inspect Delphi state

Przypadki brzegowe

  • ANSI paths may work in tests and fail for customer names or localized folders
  • ActiveX registration can succeed for one bitness and fail for another host
  • callbacks must not outlive buffers owned by the caller
  • uncaught native exceptions can terminate hosts that cannot inspect Delphi state

Delphi / C++Builder notes

PDFlibPas should sit behind a small service boundary that receives files, streams, profiles, and credentials, then returns output paths, warnings, metrics, and validation status. Important terms include DLL, ActiveX, Dylib, calling convention, buffer ownership, Unicode path.

Przykład kodu Delphi

Poniższy szkic Delphi pokazuje praktyczną granicę usługi dla tego tematu. Kontrole zasad, logowanie i walidację trzymaj poza wąskim blokiem wywołań produktu, aby przepływ pozostał testowalny.

procedure LoadPdfEngineForHost(const LibraryPath: string);
begin
  RequireFileExists(LibraryPath);
  FEngine := TPDFlib.Create;
  FHostAdapter := CreateHostAdapter(FEngine);
  FHostAdapter.RegisterErrorCallback(LogPdfEngineError);
  FHostAdapter.RegisterBufferReleaseCallback(ReleaseReturnedBuffer);
end;

Lista produkcyjna

  • Uruchom przepływ pracy na pustym pliku, zwykłym pliku klienta i pliku z najgorszego scenariusza
  • Otwórz wygenerowany plik PDF w docelowej przeglądarce, walidatorze, drukarce lub aplikacji nadrzędnej
  • Zaloguj wersję produktu, wersję profilu, hash wejścia, ścieżkę wyjścia, czas wykonania i liczbę ostrzeżeń
  • Przechowuj hasła, certyfikaty, pliki tymczasowe i dane klienta zgodnie z jednoznacznymi zasadami retencji
  • Dodaj dokument regresyjny, gdy plik klienta ujawni nowy przypadek brzegowy

Dokumentacja produktu

PDFlibPas

Dodatkowe przykłady kodu

var
  Inst, Doc: Integer;
begin
  Inst := DLCreateLibrary;                       // one instance per worker thread
  try
    Doc := DLLoadFromFile(Inst, 'in.pdf', '');   // returns a DocumentID, 0 on failure
    if Doc <> 0 then
    begin
      DLEncrypt(Inst, 'owner-secret', 'user-secret', 3,
        DLEncodePermissions(Inst, 1, 0, 0, 0, 0, 0, 0, 1));
      DLSaveToFile(Inst, 'out.pdf');
    end;
  finally
    DLReleaseLibrary(Inst);                      // frees every document the instance owns
  end;
end;
var
  P: PWideChar;
  PageText: string;
begin
  P := DLGetPageText(Inst, 7);   // pointer into a library-owned buffer
  PageText := P;                 // copy now; a later call may reuse the buffer
end;