C ABI¶
Oxiland tip 0.13.0 ships a source-compatible Redland-shaped C library
(oxiland-capi, version 0.13.0, publish = false) with a frozen allowlist.
Use this surface for world → storage → model → parse/serialize → ASK/SELECT
workflows against Oxiland. Milestone 0.11 demonstrated a Redland-compatible
shared library name (librdf.0 / librdf.so.0) for binary ABI interchange;
tip 0.13 retains that packaging and the optimized C paths. Remaining behavioral
gaps are listed in the limitations guide.
Verified matrix
Milestone 0.11 closed the source corpus and librdf-compat packaging gates on
the frozen targets/profiles; tip 0.13 retains that evidence. Read
C ABI limitations for remaining behavioral gaps
(factories, iostream tagging, log surface). Interchange evidence lives under
compatibility/downstream/ and compatibility/qualification/.
Prerequisites¶
- Rust 1.87+ (edition and MSRV used by the workspace)
- A C compiler (
cc/ Clang / GCC) - A clone of this repository —
oxiland-capihaspublish = falseand is not on crates.io
Build the library¶
From the repository root:
The default build enables Fjall. To compile an optional durable backend into
the C library, pass its matching feature, for example
--features storage-sqlite or --features storage-lmdb.
Artifacts (paths relative to the repo root):
| Artifact | Path |
|---|---|
| Static library | target/release/liboxiland_capi.a |
| Shared library (macOS) | target/release/liboxiland_capi.dylib |
| Shared library (ELF) | target/release/liboxiland_capi.so |
| Compat shared library (macOS) | target/release/compat/librdf.0.dylib (+ librdf.dylib) |
| Compat shared library (ELF) | target/release/compat/librdf.so.0 (+ librdf.so) |
| Header | crates/oxiland-capi/include/librdf.h |
| pkg-config template | crates/oxiland-capi/oxiland.pc.in |
| Drop-in Redland pkg-config | crates/oxiland-capi/librdf-compat.pc.in |
| Symbol version script (ELF) | crates/oxiland-capi/symbols.version (OXILAND_0.11 + LIBRDF_1.0.17) |
Debug builds place the same libraries under target/debug/.
Redland-compatible packaging (0.11)¶
On macOS the script sets @rpath/librdf.0.dylib via install_name_tool. On
Linux it sets soname librdf.so.0 with patchelf when available. Point
DYLD_LIBRARY_PATH / LD_LIBRARY_PATH (or pkg-config) at
target/release/compat for load-without-rebuild checks:
Compile and link (repo root)¶
Canonical one-liner from the repository root (debug build + example):
cargo build -p oxiland-capi
cc -I crates/oxiland-capi/include -L target/debug \
crates/oxiland-capi/examples/preview_workflow.c \
-loxiland_capi -Wl,-rpath,$PWD/target/debug \
-o preview_workflow
Release variant:
cargo build -p oxiland-capi --release
cc -I crates/oxiland-capi/include -L target/release \
crates/oxiland-capi/examples/preview_workflow.c \
-loxiland_capi -Wl,-rpath,$PWD/target/release \
-o preview_workflow
-Wl,-rpath,$PWD/target/debug (or .../release) is the usual macOS pattern so
the dynamic loader finds liboxiland_capi.dylib without installing it. On Linux
you may use -Wl,-rpath,$PWD/target/debug the same way, or set
LD_LIBRARY_PATH.
Link with -loxiland_capi (the cdylib / staticlib name is liboxiland_capi).
pkg-config¶
- Copy
crates/oxiland-capi/oxiland.pc.into a writable location (for example./oxiland.pc). - Substitute
@PREFIX@and@VERSION@(use0.13.0for the C API crate). - Put that directory on
PKG_CONFIG_PATHand query flags:
sed 's|@PREFIX@|'"$PWD"'/stage|g; s|@VERSION@|0.13.0|g' \
crates/oxiland-capi/oxiland.pc.in > ./oxiland.pc
export PKG_CONFIG_PATH="$PWD:${PKG_CONFIG_PATH:-}"
pkg-config --cflags --libs oxiland
The template ships Name: oxiland and links -loxiland_capi.
For a Redland drop-in name (-lrdf), use librdf-compat.pc.in (or the
redland.pc written by scripts/package-librdf-compat.sh under
target/release/compat/).
Frozen development snapshot¶
Only the symbols declared in the shipped header are exported. Unsupported Redland APIs are omitted rather than stubbed.
| Area | Symbols |
|---|---|
| World | construction, logging, and logger callbacks |
| Storage | construction, open, discovery, and sync |
| Model | CRUD, streams, sync, string export, SPARQL Update, and queries |
| Terms | URI, node, and statement construction, accessors, mutation, and string forms |
| I/O | parser/serializer names plus string, counted-string, and file variants |
| Query | ASK, SELECT, CONSTRUCT/DESCRIBE graph streams, and result iteration |
| Utilities | MD5/SHA digests, UTF-8/Latin-1 conversion, basename, and allocator release |
Handle ownership¶
Opaque handles follow the contract in design/0.8-cabi.md (handle matrix, allocator, panic containment):
- Free handles only with the matching
librdf_free_*. - Free library-returned strings only with
librdf_free_memory. NULLfree is a no-op; everyextern "C"entry contains panics viacatch_unwind.
Storage names¶
librdf_new_storage accepts "memory", "fjall", and any optional backend
compiled into oxiland-capi ("redb", "rocksdb", "sqlite", or "lmdb";
durable names use name as their path). Known optional backends that are not
compiled fail with an explicit unsupported message distinct from unknown
names—the same registry as Rust StorageBackend::from_name.
Evidence¶
Compatibility claims for this surface are scoped in the 0.9 report, the 0.10 qualification report, and the parity ledger.