BoxliteErrorCode; there are no exceptions to catch. Initialize CBoxliteError error = {0}; and free it on failure.
Prerequisites
- The BoxLite C library and headers and a machine with hardware virtualization — see Installation.
- Toolchain: a C11-compatible GCC or Clang; optionally CMake 3.15+.
- Build artifacts: build the C SDK from the repository source first to produce the shared library and header:
Quick Example
The shortest runnable path is the Simple API: it creates and holds the runtime internally, runs commands synchronously, buffers stdout/stderr into the result struct, and requires no manual drain of callbacks. Save the following ashello.c:
python:slim image and takes longer):
Native API (callback model)
Use the Native API when you need streaming output, custom configuration (volumes/ports/network/secrets), or multiple boxes. It uses a post-and-drain async model:- Call something like
boxlite_create_box(runtime, opts, cb, user_data, &error), passing a completion callback. - The SDK runs the work in an internal Tokio task and posts the completion event to the runtime queue; the call itself returns immediately (only argument-validation errors are returned via
out_error). - Call
boxlite_runtime_drain(runtime, timeout_ms, &error)on the current thread, which takes events off the queue and runs callbacks on the calling thread. If you never call drain, your callbacks never fire.
boxlite_box_exec is the exception: it returns a CExecutionHandle* synchronously (not via a callback). But boxlite_execution_wait, used to get the exit code, is callback-style and still needs drain. Streaming stdout/stderr is registered via boxlite_execution_on_stdout / boxlite_execution_on_stderr callbacks, which are also dispatched by drain.
Save the following as native.c:
gcc command, swapping hello.c for native.c).
Running Examples
BoxLite ships 8 C examples underexamples/c, built with CMake. The provided CMakeLists.txt already sets BUILD_RPATH to the library directory, so the built binaries find libboxlite.* without any manual LD_LIBRARY_PATH / DYLD_LIBRARY_PATH export.
examples/c/):
Parameters and returns
Error convention
For every function that returnsBoxliteErrorCode: Ok (0) means call-level success; non-zero means an argument/synchronous error, with details written to the CBoxliteError* (i.e. FFIError) you pass. For callback-style functions, the business result (whether creation succeeded, the exit code, etc.) is returned through the CBoxliteError* parameter inside the callback, judged separately from the synchronous return value.
The complete enum has 22 entries (
Ok = 0 through SessionReaped = 21, verified against sdks/c/include/boxlite.h). Common ones:
Simple API
CBoxliteExecResult:
Native API core functions
timeout_ms semantics for boxlite_runtime_drain:
BoxliteCommand: command (required, non-NULL), args/argc, env_pairs (interleaved [k0,v0,k1,v1,...])/env_count, workdir, user, timeout_secs (double, 0.0 = no timeout), tty (int).
Memory and ownership (always free)
All
*_free functions are NULL-safe.
Troubleshooting
The linker/runtime cannot find the library
Errordyld: Library not loaded: @rpath/libboxlite.dylib (macOS) or error while loading shared libraries: libboxlite.so (Linux).
The dynamic linker was not told the library path. Set it:
examples/c/CMakeLists.txt already sets BUILD_RPATH, so no manual export is needed).
The callback never fires / the program hangs
The most common Native API pitfall: after calling a callback-style function such asboxlite_create_box / boxlite_execution_wait, you did not call boxlite_runtime_drain. These functions post work to the queue and return immediately; the callback runs on the current thread only during drain. Always call boxlite_runtime_drain(runtime, -1, &err) in a loop while waiting for completion (see drain_until in the Quick Example).
Compile error implicit declaration of function 'boxlite_execute'
boxlite_execute does not exist in the current header. To run a command, use boxlite_box_exec(handle, &cmd, &out_execution, &error). Likewise boxlite_create_box / boxlite_execution_wait are callback-style (with cb, user_data parameters) — follow sdks/c/include/boxlite.h.
Box creation fails: Image error / non-zero exit code
A failed image pull (the first run needs network) or network flakiness returns Image (8) / Network (9). Check the network, image name spelling (e.g. "alpine:3.19"), and disk space df -h ~/.boxlite; add RUST_LOG=debug ./hello for detailed logs. Note: a non-zero exit code from the command itself (e.g. ls /nonexistent) does not make boxlite_simple_run/boxlite_box_exec return non-Ok — they return Ok, and the exit code is in result->exit_code / the exit_code of on_wait, which you must check yourself.
UnsupportedEngine or kvm: Permission denied on Linux
No hardware virtualization is available (an environment constraint). Check and enable KVM:
/dev/kvm; it uses the built-in Hypervisor.framework. macOS Intel is not supported and returns UnsupportedEngine (or crashes) — use an ARM64 Mac or Linux instead.
Memory leaks
Diagnose withvalgrind --leak-check=full ./hello (Linux) or leaks -atExit -- ./hello (macOS). Common causes: missing boxlite_error_free (free error.message even on the failure path), boxlite_free_string, boxlite_result_free, boxlite_execution_free.
Thread safety
CBoxliteRuntime can be called concurrently from multiple threads; but CBoxHandle / CBoxliteSimple / CExecutionHandle cannot be shared across threads. Callbacks run on the thread that calls boxlite_runtime_drain — do not block inside a callback.
