A `{.ffi.}` proc that returns a registered struct now delivers it natively
instead of CBOR-encoding it. The FFI-thread handler builds the return's
`<T>Pod` mirror on the heap (`nimToPod`) and stashes it on the request; the
callback receives it as a typed `const <T>*` (msg = pointer, len = sizeof), and
handleRes deep-frees it the instant the callback returns — callback-lifetime
ownership, the caller frees nothing.
Mechanics: FFIThreadRequest gains respPod/respPodLen/respPodFree fields that
handleRes honors ahead of the byte payload; the macro emits a per-proc
cdecl freer (`freePod` + `ffiCFree`) for the response POD. String and
seq[byte] returns still travel as raw bytes; the CBOR path (`<name>_cbor`) is a
separate handler and is unchanged. The C header documents the new return shape.
Validated end-to-end from C (EchoResponse, ComplexResponse with nested
seq/option graphs) including under ASAN — no UAF or double-free.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A single {.ffi.} definition now produces BOTH interfaces, chosen by the
caller at link time rather than by a global compile flag:
- `<name>` — native typed-arg C export. Args travel to the FFI thread in
a c_malloc'd C-POD struct passed by pointer (no CBOR), and the
result is delivered to the callback as raw bytes. This is the
preferred path for same-process callers: no serialization on
either side.
- `<name>_cbor` — the existing CBOR-buffer dispatcher, kept for generic /
cross-language callers.
Both share the user's helper proc; they register distinct handlers keyed by
"<Camel>Req" (CBOR) and "<Camel>ReqNative". FFIThreadRequest gains a `cborMode`
flag and a `payloadFree` hook so the native C-POD payload (which owns duplicated
cstring fields) is released correctly and an empty native result is delivered as
a zero-length buffer instead of the CBOR null sentinel. alloc.nim gains
ffiCMalloc/ffiCFree (prefixed to avoid Nim's style-insensitive clash with
ansi_c.c_malloc/c_free).
Verified end-to-end on a scalar-param lib: native calls return raw strings
("calc v1", "sum=42"); the _cbor variant still returns CBOR.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* protect against mem leak in case of failures sending requests to ffi thread
* better cleanup if failures in createFFIContext
* avoid dangling cstring in handleRes under ARC/ORC
* better resource cleanup in destroyFFIContext
* invoke onNotResponding if failure in destroyFFIContext
* correct seq copy in alloc
* make sure the lock is init before cleanUpResources
* better possible exception handling in processReq
* guard allocSharedSeq if given seq is empty
* enhance error handling in ffi_context
* add new tests and some corrections