ABI stability
The C ABI has an explicit version surface and a generated header. ABI stability means C callers can rely on ownership and layout rules within the documented version boundary.
Current version: 5
The ABI is version 5, reported by machbus_session_abi_version().
C examples intentionally fail fast if the runtime reports a different version.
That guard is the only thing standing between a stale header and undefined
behaviour, so it is load-bearing: a caller built against v3 that skipped it
would call the five-argument machbus_session_fs_client_seek with four
arguments, reading out_tan from an uninitialised stack slot and writing
through it.
v4 → v5
The largest change is a removal: the Guidance subsystem is gone, superseded
by AutoDrive.
-
All twelve
machbus_session_guidance_*functions are removed, along withMachbusConfig::enable_guidanceand theMACHBUS_EVENT_KIND_GUIDANCE_STOP_REQUESTEDevent kind.GuidanceandAutoDrivewere mutually exclusive authors of PGN 0xAD00 with ~80 % duplicated safety logic; every audit round had to fix both, identically. Port to themachbus_session_autodrive_*family:removed replacement guidance_engageautodrive_armthenautodrive_engageguidance_disengageautodrive_disengageguidance_command_curvature(k)autodrive_command(NAN, k)guidance_command_radius(r)autodrive_command(NAN, 1000.0 / r)guidance_command_velocity(v, ω)autodrive_command(v, (ω / v) * 1000.0)guidance_command_straight()autodrive_command(NAN, 0.0)guidance_is_engagedautodrive_is_engagedguidance_stop_reasonautodrive_stop_reasonguidance_clear_stopautodrive_clear_stopguidance_estimated_curvaturepoll the GuidanceMachineInfoeventMachbusConfigis unchanged in size (48 bytes) and no surviving field moved, so the layout assertions still hold — but a caller that setenable_guidancewill no longer compile. -
MACHBUS_EVENT_KIND_GUIDANCE_MACHINE_INFO,_LINK_LOSTand_LINK_RESTOREDare unchanged and still fire —AutoDrivenow emits them, so an event-driven C caller reading the steering ECU’s feedback needs no change._GUIDANCE_STOP_REQUESTEDis removed becauseMACHBUS_EVENT_KIND_AUTODRIVE_SAFE_STOPsupersedes it and reports which trigger fired rather than only that something did.
Beyond that removal, the error contract of two functions changed.
machbus_session_autodrive_clear_stopandmachbus_session_guidance_clear_stopcan now returnfalse. Releasing a latched safe stop has been a conditional no-op inside the plugins since the ISB and GNSS hazard interlocks landed, but both C functions returnedtrueunconditionally and cleared the last error. A caller that showed the fault as cleared on atruereturn re-enabled Engage with the latch still set. They now returnfalseand set a last-error string naming the refusal (stop_condition_live) when the operator is still holding the Auxiliary Shortcut Button or a GNSS hazard is live.
The Python autodrive_clear_stop / guidance_clear_stop raise RuntimeError
in the same case.
-
MachbusLanguageDataunit fields now carry0xFFfor an unrecognised code instead of silently substituting the metric/English default. A Language Command whose unit codes this edition does not define is no longer discarded whole either, so a caller now receives the operator’s language code with0xFFin the fields it could not interpret. Treat0xFFas “not specified” rather than as a unit value. -
machbus_session_autodrive_stop_reasonandmachbus_session_guidance_stop_reasonreturnMachbusSafeStopTriggerinstead of a bareuint32_t. The values are unchanged — the enum mirrorsSafeStopTrigger::as_code, withMACHBUS_SAFE_STOP_TRIGGER_NONE = 0for “no stop latched” — but the return type is now named, so a C HMI no longer has to hardcode codes read out of the Rust source. Codes 2 and 3 are permanently retired (they wereTimStatusTimeoutandFunctionRequestTimeout, which had no producer); they must never be reused, or every value above them shifts for callers built against an older header. -
MachbusEventKindgainedTcServerClientDisconnected(100). Additive: existing discriminants are unchanged. It fires when the TC server drops a client after six seconds without a Client Task message (ISO 11783-10 §6.6.3);sourceis the client address. A caller with an exhaustive switch over the enum must add an arm.
v3 → v4
Conformance work against ISO 11783-13 and ISO 11783-7 changed four things a C caller must audit:
machbus_session_fs_client_seekgained an argument. It was(handle, position: uint32_t, out_tan); it is now(handle, mode: uint8_t, offset: int32_t, out_tan).modeis the ISO 11783-13 B.17 Position Mode — 0 from the start, 1 from the current pointer, 2 from the end — and the offset is signed, so a rewind is a negative value.- File Server error codes were renumbered to Annex B.9. Everything from 5
upward moved:
InvalidHandleis now 5 (was 7),MediaNotPresent10 (was 12),NotSupported12 (was 20). A caller switching on the numeric value must be re-read against the table. MachbusEvent’s FS seek payload carries the resulting position rather than a unit success, per C.3.3.3.repr(C)PODs widened where a decoder gained a field (notably the GNSS position, which now carries DD209 integrity).
v2 → v3
The rewrite onto the session facade: the entire
symbol set was renamed to the machbus_session_* prefix and the model changed
to sans-IO (the caller bridges IO with feed/tick/poll instead of an internal
virtual bus). A deliberate breaking change; stability guarantees start fresh
from v3, and older machbus.h headers and pre-v3 symbol names do not apply.
What the version covers
Bump the ABI version whenever any of these change in a way C callers must audit:
- exported function signatures,
#[repr(C)]POD struct layouts (MachbusConfig,MachbusEvent, …),- enum discriminants (
MachbusClaimState,MachbusEventKind, the command enums), - ownership or error contracts.
What is checked
- generated header drift (
include/machbus.hagainstsrc/ffi.rs), - exported function compile surface,
- C POD layout assertions,
- Rust-side FFI contract tests,
- C demo workflows.
When changing ABI
- Update the Rust FFI code in
src/ffi.rs. - Bump
MACHBUS_C_ABI_VERSIONif the change is caller-visible. - Regenerate and check the header (
make bind-c,make bind-c-check). - Update examples.
- Run
make verify. - Document the change in release notes.