Ivan FB f08cb7971d
feat(codegen): C native event payloads + -d:ffiMode (native/cbor/both) + tasks
- Add the `-d:ffiMode=native|cbor|both` strdefine (default both) with
  `ffiEmitNative`/`ffiEmitCbor` helpers; the C generator now emits only the
  selected header(s) (`<lib>.h` and/or `<lib>_cbor.h`).
- Native C events: the native header documents each event's payload type
  (`"on_echo_fired" -> const EchoEvent *`) so consumers cast the callback's msg
  to the typed struct — the bare native listener already delivers it.
- nimble tasks: `genbindings_c` (both), `genbindings_c_native`,
  `genbindings_c_cbor`.

Verified: native mode emits only my_timer.h, cbor only my_timer_cbor.h, both
emits both.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 18:37:27 +02:00
..
2026-05-25 15:51:56 +02:00
2026-05-21 16:33:38 +02:00

timer example

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) <lib>.h / <name> Same-process / local calls. Flat C structs by value, zero serialization.
CBOR <lib>_cbor.h / <name>_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/). The per-language examples below: native C (c_bindings/), native Go (go_bindings/), native/CBOR C++ (cpp_bindings/), CBOR Rust (rust_client/), and CBOR-over-socket IPC (ipc/).

Usage

  1. Change into the example directory:

    cd examples/timer
    
  2. Install the local ffi dependency:

    nimble install -y ../..
    
  3. Build the example library:

    nimble build
    
  4. Generate bindings:

    nimble genbindings_rust
    nimble genbindings_cpp
    

Rust example clients

The Rust client lives in examples/timer/rust_client.

  • Run the sync example:

    cd examples/timer/rust_client
    cargo run --bin rust_client
    
  • Run the Tokio example:

    cd examples/timer/rust_client
    cargo run --bin tokio_client
    

C++ example

The generated C++ example lives in examples/timer/cpp_bindings.

Build and run it with:

cd examples/timer/cpp_bindings
cmake -S . -B build
cmake --build build
./build/example