Stabilne ABI wywołań zwrotnych C w HotPDF

HotPDFABI.dll wystawia płaskie funkcje cdecl ze statusami o stałej szerokości, nieprzezroczystymi uchwytami, jawnymi długościami w bajtach oraz wersjonowaną strukturą wywołań zwrotnych hpdf_io_v1 zadeklarowaną w Lib/hotpdf_abi.h

Wyniki budowania

Uruchom build-HotPDF-ABI.cmd, aby zbudować DLL-e Win32 i Win64 plus biblioteki importu pod Lib/ABI/<platform>/Release

Publiczne ABI używa stabilnych małoliterowych nazw eksportów, a hpdf_abi_version i hpdf_abi_io_v1_size pozwalają wywołującym zweryfikować kontrakt przed utworzeniem dokumentu

Funkcje główne

uint32_t hpdf_abi_version(void);
uint32_t hpdf_abi_io_v1_size(void);
hpdf_status hpdf_document_create(hpdf_document *handle);
hpdf_status hpdf_document_destroy(hpdf_document handle);
hpdf_status hpdf_document_load_from_io(
    hpdf_document handle,
    const hpdf_io_v1 *io,
    const char *password,
    size_t password_length);
hpdf_status hpdf_document_page_count(
    hpdf_document handle,
    uint32_t *page_count);
hpdf_status hpdf_document_save_to_io(
    hpdf_document handle,
    const hpdf_io_v1 *io);

Wersjonowana struktura I/O

hpdf_io_v1 io = {0};
io.struct_size = sizeof(io);
io.abi_version = HPDF_ABI_VERSION_1;
io.user_data = state;
io.read_at = read_at;
io.get_size = get_size;
io.write = write;
io.is_cancelled = is_cancelled;
io.progress = progress;
io.diagnostic = diagnostic;

struct_size to 48 bajty na Win32 i 72 bajty na Win64, flags muszą być zerem dla ABI v1, a większe przyszłe struktury można rozróżnić bez zgadywania układu pól

Wszystkie wywołania zwrotne i eksportowane funkcje używają cdecl, każdy wskaźnik tekstu ma jawną długość w bajtach, a żadne ciągi, klasy, interfejsy, enumy, wyjątki ani Boolean z Delphi nie przekraczają granicy

Wejście o dostępie swobodnym

read_at otrzymuje bezwzględny offset 64-bit i pisze bezpośrednio do bufora docelowego parsera, a get_size raportuje niezmienny rozmiar źródła raz, gdy źródło jest podłączane

Częściowe udane odczyty są przyjmowane i uzupełniane przez powtarzane wywołania zwrotne, więc magazyny zakresowe i ograniczone czytniki sieciowe nie muszą alokować pośredniego bufora całego pliku

Stan wywołania zwrotnego i bajty źródła muszą pozostać ważne, dopóki uchwyt dokumentu nie zostanie zniszczony albo do uchwytu nie zostanie załadowane inne źródło

Wyjście strumieniowe

write otrzymuje sekwencyjne fragmenty wyjścia bezpośrednio z SaveLoadedDocumentToStream; częściowe udane zapisy są ponawiane, dopóki kompletny fragment nie zostanie przyjęty

Udany zapis o zerowej liczbie bajtów jest odrzucany jako błąd I/O, bo nie może zrobić postępu do przodu

Dla operacji execute JSON i porównania dwóch uchwytów nieudany callback zapisu nie jest wywoływany ponownie, by publikować wynik błędu przez tę samą parę writer i user-data, także gdy OutputIO i ResultIO współdzielą tę parę; częściowe bajty kandydata już dostarczone wywołującemu pozostają jego odpowiedzialnością

Wartości statusu zapisu poza zdefiniowanym niezerowym zakresem statusów oraz zerowe albo nadmierne udane liczby bajtów stają się HPDF_STATUS_IO_ERROR; layout rekordu V1 i zachowanie częściowych udanych zapisów pozostają niezmienione

Status i cykl życia

StatusZnaczenie
HPDF_STATUS_OKOperacja się zakończyła
HPDF_STATUS_INVALID_ARGUMENTBrak wymaganego wskaźnika lub wywołania zwrotnego albo zakres bajtów jest nieprawidłowy
HPDF_STATUS_INVALID_HANDLEUchwyt jest nullem, nieznany albo już zniszczony
HPDF_STATUS_INCOMPATIBLE_ABIRozmiar struktury, wersja lub flagi są nieobsługiwane
HPDF_STATUS_CANCELLEDWywołanie zwrotne anulowania zażądało zakończenia
HPDF_STATUS_IO_ERRORWywołanie zwrotne wejścia lub wyjścia zawiodło albo naruszyło swój kontrakt liczbowy
HPDF_STATUS_PARSE_ERRORWejście zostało odczytane poprawnie, ale nie zostało zaakceptowane jako PDF
HPDF_STATUS_INTERNAL_ERRORWewnętrzna awaria została przechwycona, zanim przekroczyła ABI

Każde udane hpdf_document_create musi mieć parę w postaci jednego udanego hpdf_document_destroy; powtórzone niszczenie zwraca HPDF_STATUS_INVALID_HANDLE

Nieprzezroczyste uchwyty to monotoniczne tokeny lokalne dla procesu, a nie adresy obiektów, więc ponowne użycie alokatora nie wskrzesi nieaktualnego uchwytu

Wyjątki nigdy nie przekraczają granicy C, a opcjonalne wywołanie zwrotne diagnostyki otrzymuje odpowiadające bajty komunikatu, zanim operacja zwróci status błędu

Współbieżność

Różne uchwyty mogą być używane współbieżnie, ale wywołujący muszą szeregować operacje i niszczenie dla tego samego uchwytu

Starsze wywołania zwrotne Pascal

THPDFABICallbacks i pomocniki Pascal HPDFDoc* pozostają zgodne na poziomie źródeł dla aplikacji Delphi i C++Builder, ale natywne integracje C powinny używać hotpdf_abi.h i małoliterowych eksportów v1