mirror of
https://github.com/logos-messaging/nim-ffi.git
synced 2026-06-21 00:40:16 +00:00
The recycle/async-destroy work changed the Nim `ffiDtor` export from `int destroy(ctx)` to `int destroy(ctx, callback, userData)`, but the C++ and Rust generators still emitted the 1-arg signature. Foreign callers therefore passed only `ctx`; inside Nim, `callback`/`userData` held uninitialised register garbage. `requestRecycle` stored the garbage callback and the recycle handler later invoked it — a jump through a wild pointer that segfaulted in every C++ E2E / ASan / TSan job (the crash surfaced at teardown, after each test's assertions had already passed). Generate the 3-arg ABI and have the destructor/Drop block on the recycle callback via the existing sync-call helper, so the pool slot is fully drained and parked before the handle goes away — otherwise rapid create/destroy churn (StressShortLivedPerThreadContext, ThreadedHammer) could outrun the recycle and exhaust the pool. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
timer example
This example is a self-contained Nimble project demonstrating how to import nim-ffi and use the .ffiCtor. / .ffi. abstraction.
Usage
-
Change into the example directory:
cd examples/timer -
Install the local
ffidependency:nimble install -y ../.. -
Build the example library:
nimble build -
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