pdf_oxide
June 27, 2026 · View on GitHub
Idiomatic Zig bindings over the pdf_oxide C ABI via @cImport — first-class C
interop, no shim. Handles are structs with deinit; returned C strings/buffers
are copied into a caller-provided allocator and the C buffer freed via
free_string; non-success C-ABI error codes map to error.PdfOxide.
Pinned to Zig 0.15.1 (pre-1.0 — the build/C-import API drifts between releases). CI uses the same version.
Install
Zig has no central registry — depend on a release tarball by URL + content hash.
zig fetch --save downloads it, computes the hash, and writes the dependency
into your build.zig.zon:
zig fetch --save https://github.com/yfedoseev/pdf_oxide/archive/refs/tags/v0.3.69.tar.gz
Then in build.zig:
const pdf_oxide = b.dependency("pdf_oxide", .{});
exe.root_module.addImport("pdf_oxide", pdf_oxide.module("pdf_oxide"));
The wrapper links the native libpdf_oxide cdylib — see "Build & test" for
building it and pointing the build at the header + library.
Build & test
The binding links the default-feature cdylib (not the Python wheel):
# 1. build the native library (shipped binding feature set)
cargo build --release --lib --features ocr,rendering,signatures,barcodes,tsa-client,system-fonts
# 2. test + run the example (point at the header + cdylib)
cd zig
LD_LIBRARY_PATH="$PWD/../target/release" \
zig build test -DPDF_OXIDE_INCLUDE_DIR="$PWD/../include" -DPDF_OXIDE_LIB_DIR="$PWD/../target/release"
LD_LIBRARY_PATH="$PWD/../target/release" \
zig build example -DPDF_OXIDE_INCLUDE_DIR="$PWD/../include" -DPDF_OXIDE_LIB_DIR="$PWD/../target/release"
Use
const pdf_oxide = @import("pdf_oxide");
var pdf = try pdf_oxide.Pdf.fromMarkdown("# Hello\n\nbody\n");
defer pdf.deinit();
const bytes = try pdf.toBytes(allocator);
defer allocator.free(bytes);
var doc = try pdf_oxide.Document.openFromBytes(bytes);
defer doc.deinit();
const text = try doc.extractText(allocator, 0);
defer allocator.free(text);
Layout
zig/
lib/pdf_oxide.zig @cImport wrapper (Document, Pdf) + api-coverage tests
examples/basic_extraction.zig runnable example (asserted in CI)
build.zig / build.zig.zon
Verification (CI — same set as every binding)
.github/workflows/zig.yml on Linux + macOS: build cdylib → pinned Zig 0.15.1 →
zig build test (api-coverage) → zig build example with an output assertion.