Skip to content

ffi: generate sandlock.h with cbindgen#87

Merged
congwang-mk merged 2 commits into
mainfrom
ffi/cbindgen-sandlock-header
Jun 2, 2026
Merged

ffi: generate sandlock.h with cbindgen#87
congwang-mk merged 2 commits into
mainfrom
ffi/cbindgen-sandlock-header

Conversation

@congwang-mk
Copy link
Copy Markdown
Contributor

What

Replaces the hand-maintained crates/sandlock-ffi/include/sandlock.h with one generated from the crate's #[no_mangle] exports by cbindgen, and adds a CI gate so the header can never drift from the source again.

Why

While reviewing the Go SDK (#83), the C header was found to be both stale and divergent: it declared only 50 of the 69 symbols the bindings call, and a class of latent type mismatches had crept in (for example boolean setters that the header, Rust, and Python all spell bool but which other consumers had transcribed as unsigned char). The header was curated by hand for the handler docs and was not kept in lockstep with the builder, lifecycle, and dry-run surfaces. Generating it makes it authoritative and complete, so downstream consumers (the C test, and a future Go binding) can #include it instead of re-transcribing prototypes.

How

  • crates/sandlock-ffi/cbindgen.toml: cbindgen config. Opaque #[repr(C)] wrappers and foreign sandlock-core types are forward-declared; the two action/exception enums are force-emitted (they are referenced from Rust only via as u32 casts, so cbindgen would otherwise drop them); type and enum-variant renames preserve the established C names (sandlock_builder_t, SANDLOCK_EXCEPTION_KILL, SANDLOCK_ACTION_INJECT_FD_SEND, ...).
  • src/handler/abi.rs: sandlock_handler_new now spells its two callback parameters as inline Option<extern "C-unwind" fn(...)> rather than via the sandlock_handler_fn_t / sandlock_handler_ud_drop_t aliases. A type alias is the same type to Rust, so this is ABI-identical and the body is unchanged, but cbindgen only flattens Option<fn> into a nullable C function pointer when the fn is written inline; Option<NamedAlias> is emitted as an uncallable opaque by-value struct. The aliases remain in use by the struct fields and the Rust tests.
  • .github/workflows/ci.yml: a cbindgen-header job regenerates the header and fails on any diff from the committed copy.
  • build.rs: comment updated to reflect generation (the build still does not run cbindgen, so a plain cargo build needs no extra tooling).
  • .gitignore: keep tracking the generated header while still ignoring other artifacts under include/.

Verification

  • The generated header compiles standalone as both C and C++.
  • crates/sandlock-ffi/tests/c/handler_smoke.c compiles against it unchanged, confirming the C names and the now-callable sandlock_handler_new signature.
  • Bidirectional symbol parity: every function declared in the header is backed by an exported symbol in libsandlock_ffi.so, and every exported sandlock_ symbol is declared in the header.
  • cargo test -p sandlock-ffi: 49 passed (the handler-interception tests exercise the touched ABI). The only failure is the preexisting libLLVM doctest stub issue on this host, unrelated to the change.
  • Regeneration is idempotent, so the new CI gate passes.

🤖 Generated with Claude Code

Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
@congwang-mk congwang-mk merged commit 6aaf465 into main Jun 2, 2026
10 checks passed
@congwang-mk congwang-mk deleted the ffi/cbindgen-sandlock-header branch June 2, 2026 00:14
dzerik added a commit to dzerik/sandlock that referenced this pull request Jun 2, 2026
Header is now cbindgen-generated (upstream switched in multikernel#87). The manual
header edits from the original Protection commits are dropped; the C ABI
for the Protection setters is regenerated from the #[no_mangle] Rust
definitions instead. CI verifies the committed header matches a fresh
generation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant