mirror of
https://github.com/logos-messaging/nim-ffi.git
synced 2026-06-21 00:40:16 +00:00
The C codegen already emitted `my_timer.h` / `my_timer_cbor.h`, but the example had no runnable driver. Add `example.c` exercising the native ABI end-to-end (ctor with a struct param, string-returning version, struct-param echo, and a deeply nested ComplexRequest), plus a Makefile that builds the Nim dylib from the repo root — where the vendored Nimble deps resolve — and links the driver. Native is the same-process path; the companion CBOR headers are for crossing a process/machine boundary (see the forthcoming ipc example). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
40 lines
1.8 KiB
Markdown
40 lines
1.8 KiB
Markdown
# C bindings — native (same-process) example
|
|
|
|
Generated C headers for the timer library plus a small driver that links the
|
|
library directly and calls the **native** (zero-serialization) ABI.
|
|
|
|
## Files
|
|
|
|
| File | Description |
|
|
|------|-------------|
|
|
| `my_timer.h` | Native ABI: each `{.ffi.}` type is a plain C `struct`, passed by value to `int <name>(ctx, cb, ud, <args…>)`. Results arrive on the callback. Best for same-process callers — no serialization. |
|
|
| `my_timer_cbor.h` | CBOR ABI (`<name>_cbor`): request/response as CBOR bytes. Use this when the call crosses a process or machine boundary. See [`../ipc`](../ipc). |
|
|
| `example.c` | Native same-process driver: create → version → echo → complex → destroy. |
|
|
| `Makefile` | Builds the Nim dylib (from the repo root) and the driver. |
|
|
|
|
The headers are regenerated by `nimble genbindings_c` (run from the repo root)
|
|
and overwritten each time — don't edit them by hand.
|
|
|
|
## Build & run
|
|
|
|
```sh
|
|
cd examples/timer/c_bindings
|
|
make run
|
|
```
|
|
|
|
This compiles `libmy_timer.{dylib,so}` and runs `./example`, which prints the
|
|
library version and the round-tripped echo/complex responses. Every call is
|
|
dispatched on the library's FFI thread, so the driver blocks on a condvar-backed
|
|
callback for each result.
|
|
|
|
## Native vs CBOR
|
|
|
|
The native path passes `{.ffi.}` structs as flat C-POD values (`const char*` for
|
|
strings, `{ T* ptr; size_t len }` for sequences, `{ int present; T }` for
|
|
options). Arguments are **deep-copied** across the FFI-thread boundary, so the C
|
|
caller's buffers can be freed immediately after the call returns. String returns
|
|
come back raw; struct returns are CBOR-encoded inside the callback payload.
|
|
|
|
For the cross-process / cross-machine path, the same library is reached over a
|
|
socket using the CBOR ABI — see [`../ipc`](../ipc).
|