|
nros platform-cffi
Canonical C ABI for porting the nros platform abstraction
|
Canonical C ABI for porting the nano-ros platform abstraction in C (or any language with a C ABI). Use this surface when nano-ros's pre-built platform support (POSIX, Zephyr, FreeRTOS, NuttX, ThreadX) does not cover your target and your port stays in C.
The ABI is a set of free extern "C" symbols — one per platform capability. Each rule (buffer ownership, threading, blocking allowance) is documented on the corresponding function declaration below. The binary links exactly one platform implementation; resolution is performed at link time. There is no runtime registration step.
This sits one tier below the Phase 117 RMW vtable (<nros/rmw_vtable.h>). The RMW layer is a runtime-pluggable struct of function pointers because RMW backends genuinely swap per session. The platform layer is link-time-bound free symbols because a platform is fixed for the life of a binary.
Build nano-ros with the platform-cffi option enabled:
Implement the platform symbols in C:
See <nros/platform.h> for the full list and the per-function return-value / threading / blocking conventions. The capability split:
nros_platform_clock_ms, ..._clock_us) — monotonic counternros_platform_alloc, ..._realloc, ..._dealloc) — heap interfacenros_platform_sleep_us, ..._sleep_ms, ..._sleep_s) — blocking sleepnros_platform_yield_now) — cooperative-yield primitivenros_platform_random_u8 … ..._random_u64, ..._random_fill) — entropynros_platform_time_now_ms, ..._time_since_epoch_*) — wall clocknros_platform_task_*) — spawn / join / detach / cancel / exit / freenros_platform_mutex_* non-recursive, ..._mutex_rec_* recursive)nros_platform_condvar_*, including ..._condvar_wait_until)A platform that lacks a capability (e.g., bare-metal with no kernel threads) can still satisfy the ABI by stubbing out the missing ops:
| Op family | Stub behaviour |
|---|---|
task_* | task_init returns -1; the rest unreachable. |
mutex_* / mutex_rec_* | All return 0; storage is a no-op. Safe on single-core no-preempt systems. |
condvar_* | signal/signal_all return 0; wait/wait_until return -1 so callers fall back to polling. |
random_* | Seeded LCG is fine if the platform has no entropy source. Must be deterministic for reproducible tests. |
Rust platform crates (e.g. nros-platform-posix) keep implementing the [nros_platform_api] traits. A sibling -cffi shim crate re-exports the Rust impl as #[unsafe(no_mangle)] extern "C" symbols matching the names in <nros/platform.h>. The same Rust impl serves both trait-driven Rust callers and C-ABI consumers.
mutex_rec_* re-entrantly from the same thread. A non-recursive mutex backing mutex_rec_* will deadlock under load.condvar_wait_until callers compare against clock_ms(). The two must share the same monotonic origin.alloc from an ISR, but if your random_* does it must be lock-free.task_init — RTOS task stacks ship with low defaults; raise via the attr parameter.nros-platform-cffi source tree — header + Rust mirror for this ABI.