HotPDF Stable C Callback ABI

HotPDFABI.dll exposes flat cdecl functions with fixed-width status values, opaque handles, explicit byte lengths, and the versioned hpdf_io_v1 callback structure declared in Lib/hotpdf_abi.h

Build outputs

Run build-HotPDF-ABI.cmd to build Win32 and Win64 DLLs plus import libraries under Lib/ABI/<platform>/Release

The public ABI uses stable lowercase export names, while hpdf_abi_version and hpdf_abi_io_v1_size let callers verify the contract before creating a document

Core functions

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);

Versioned I/O structure

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 is 48 bytes on Win32 and 72 bytes on Win64, flags must be zero for ABI v1, and larger future structures can be distinguished without guessing field layout

All callbacks and exported functions use cdecl, every text pointer has an explicit byte length, and no Delphi string, class, interface, enum, exception, or Boolean crosses the boundary

Random-access input

read_at receives an absolute 64-bit offset and writes directly into the parser's destination buffer, while get_size reports the immutable source size once when the source is attached

Partial successful reads are accepted and completed through repeated callback calls, so range stores and bounded network readers do not need to allocate an intermediate complete-file buffer

The callback state and source bytes must remain valid until the document handle is destroyed or another source is loaded into the handle

Streamed output

write receives sequential output chunks directly from SaveLoadedDocumentToStream; partial successful writes are retried until the complete chunk is accepted

A zero-byte successful write is rejected as an I/O error because it cannot make forward progress

Status and lifecycle

StatusMeaning
HPDF_STATUS_OKThe operation completed
HPDF_STATUS_INVALID_ARGUMENTA required pointer or callback is absent or a byte range is invalid
HPDF_STATUS_INVALID_HANDLEThe handle is null, unknown, or already destroyed
HPDF_STATUS_INCOMPATIBLE_ABIThe structure size, version, or flags are unsupported
HPDF_STATUS_CANCELLEDThe cancellation callback requested termination
HPDF_STATUS_IO_ERRORAn input or output callback failed or violated its count contract
HPDF_STATUS_PARSE_ERRORThe input was read successfully but was not accepted as a PDF
HPDF_STATUS_INTERNAL_ERRORAn internal failure was caught before it crossed the ABI

Each successful hpdf_document_create must be paired with one successful hpdf_document_destroy; repeated destruction returns HPDF_STATUS_INVALID_HANDLE

Opaque handles are monotonic process-local tokens rather than object addresses, so allocator reuse cannot revive a stale handle

Exceptions never cross the C boundary, and the optional diagnostic callback receives the corresponding message bytes before an operation returns an error status

Concurrency

Different handles may be used concurrently, but callers must serialize operations and destruction for the same handle

Legacy Pascal callbacks

THPDFABICallbacks and the HPDFDoc* Pascal helpers remain source compatible for Delphi and C++Builder applications, but native C integrations should use hotpdf_abi.h and the lowercase v1 exports