From 2ec514cf9fb287f37f7f1dd71de52d1de8ed1ca9 Mon Sep 17 00:00:00 2001 From: Ivan FB Date: Sun, 31 May 2026 12:31:50 +0200 Subject: [PATCH] docs(examples): make clear the CBOR ABI is for IPC only Every generated library exports both ABIs side by side; spell out the choice in the example READMEs: the native (pure-C) ABI is the default for same-process / local calls (flat C structs, zero serialization), while the CBOR ABI exists solely for inter-process communication (different process or machine). In a shared address space CBOR is pure overhead, so prefer native locally. Co-Authored-By: Claude Opus 4.8 --- examples/timer/README.md | 11 +++++++++++ examples/timer/c_bindings/README.md | 9 +++++++++ examples/timer/ipc/README.md | 5 +++++ 3 files changed, 25 insertions(+) diff --git a/examples/timer/README.md b/examples/timer/README.md index 2a005eb..dd0bef4 100644 --- a/examples/timer/README.md +++ b/examples/timer/README.md @@ -2,6 +2,17 @@ This example is a self-contained Nimble project demonstrating how to import `nim-ffi` and use the `.ffiCtor.` / `.ffi.` abstraction. +## Two ABIs, one library + +Every generated library exports **two ABIs side by side**, and you choose per call site: + +| ABI | Header / symbols | Use it for | +|-----|------------------|------------| +| **Native (pure C)** | `.h` / `` | **Same-process / local** calls. Flat C structs by value, zero serialization. | +| **CBOR** | `_cbor.h` / `_cbor` | **Inter-process communication only** — a different process or machine, where the request must be serialized to cross the boundary. | + +In a shared address space the CBOR round-trip is pure overhead, so **default to the native ABI locally and reach for CBOR only when you actually cross a process/machine boundary** (see [`ipc/`](ipc)). The per-language examples below: native C ([`c_bindings/`](c_bindings)), native Go ([`go_bindings/`](go_bindings)), native/CBOR C++ ([`cpp_bindings/`](cpp_bindings)), CBOR Rust ([`rust_client/`](rust_client)), and CBOR-over-socket IPC ([`ipc/`](ipc)). + ## Usage 1. Change into the example directory: diff --git a/examples/timer/c_bindings/README.md b/examples/timer/c_bindings/README.md index 757f972..101c72f 100644 --- a/examples/timer/c_bindings/README.md +++ b/examples/timer/c_bindings/README.md @@ -3,6 +3,15 @@ Generated C headers for the timer library plus a small driver that links the library directly and calls the **native** (zero-serialization) ABI. +> **Which ABI?** The library exports **both** ABIs from the same shared object, +> side by side: the native `` symbols and the CBOR `_cbor` symbols. +> Use the **native (pure-C) ABI for same-process / local calls** — it passes +> flat C structs with zero serialization. Use the **CBOR ABI only for +> inter-process communication** (a different process, or a different machine), +> where the data has to be serialized to cross the boundary anyway. In one +> address space, CBOR is pure overhead — prefer native. See [`../ipc`](../ipc) +> for the CBOR/IPC path. + ## Files | File | Description | diff --git a/examples/timer/ipc/README.md b/examples/timer/ipc/README.md index 451ca33..fe8ffd3 100644 --- a/examples/timer/ipc/README.md +++ b/examples/timer/ipc/README.md @@ -6,6 +6,11 @@ library **in the same process**. When the caller lives in a *different process* request has to be serialized. That is exactly what the **CBOR ABI** (`_cbor`, declared in `my_timer_cbor.h`) is for. +> **The CBOR ABI exists solely for inter-process communication.** If you are in +> the same process as the library, use the native ABI instead — serializing to +> CBOR and decoding it on a sibling thread is pure overhead when you already +> share memory. Both ABIs ship in the same library; pick per call site. + This example wires that ABI across a socket: - **`server`** links `libmy_timer`, creates one timer context at startup, and