Skip to content

feat(codegen): native C++ generator (typed requests + events)#63

Draft
Ivansete-status wants to merge 3 commits into
native-eventsfrom
cpp-native-codegen
Draft

feat(codegen): native C++ generator (typed requests + events)#63
Ivansete-status wants to merge 3 commits into
native-eventsfrom
cpp-native-codegen

Conversation

@Ivansete-status

Copy link
Copy Markdown
Collaborator

What

Native (zero-serialization) C++ generator, emitted alongside the CBOR C++ bindings — the C++ counterpart of the native C/Go work in this stack.

  • Emits <lib>_native.hpp (plus the native <lib>.h via the C generator) with idiomatic C++ types, toC/fromC, and a <Lib>Node that blocks on std::future.
  • Holder pattern for native marshalling: a holder owns the backing storage (std::vector arrays, strings borrow the source via .c_str()) while the C-POD struct's pointers reference it for the call duration (the lib deep-copies).
  • Native typed eventsOn<Event>(std::function<void(const Payload&)>) registered through the bare native listener entry point, with extern "C" trampolines reading the raw C-POD and a std::map<uint64_t, unique_ptr<ListenerBase>> owning the handlers.
  • Static C++/CMake blocks live in ffi/codegen/templates/cpp/*.tpl (via staticRead).

Builds on #62 (native event delivery).

Test

C++ e2e suite passes; the holder memory pattern is ASAN-clean.

🤖 Generated with Claude Code

Ivansete-status and others added 3 commits May 31, 2026 18:39
A native C++ binding generator (`cpp_native.nim`), the C++ counterpart of the C
and Go native paths and companion to the CBOR `cpp.nim`. It emits
`<lib>_native.hpp`: an idiomatic C++ struct + `toC`/`fromC` per `{.ffi.}` type,
and a `<Lib>Node` class whose methods marshal typed args into / read typed
struct returns out of the native ABI (`<name>` entry points + flat C structs in
`<lib>.h`) — zero serialization. Wired into genBindings under
`targetLang=cpp` + `-d:ffiMode=native`; emits the native C header alongside so
the binding is self-contained. Task: `genbindings_cpp_native`.

First cut covers scalar/string/bool/nested-struct fields (create/version/echo);
seq/Option params are `// SKIPPED`, and native typed events are next. Filename
is `_native.hpp` for now to coexist with the CBOR `.hpp` (rename is a follow-up).

Verified end-to-end: the generated example builds and round-trips a typed
EchoResponse (`make run`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends the native C++ marshalling to sequences and optionals: a C++ field maps
to std::vector<T> / std::optional<T>, and `toC` returns a holder that owns the
C-array backing (move/NRVO-safe std::vectors) while string pointers borrow the
C++ argument — valid for the call, which the library deep-copies. `fromC` reads
seq/Option back out of the C-POD.

Unblocks the timer's complex (seq-of-structs / seq-of-strings / two optionals)
and schedule (three struct params) methods — they now generate and round-trip
typed results. Verified end-to-end and ASAN-clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the ergonomic native event surface to the C++ generator:
`node.On<Event>(std::function<void(const <Payload>&)>)` registers a native
listener; a per-event extern "C" trampoline reads the typed POD
(`fromC(*reinterpret_cast<const ::<Payload>*>(msg))`) and invokes the handler —
no CBOR. The handler is owned by the node (a `std::map` of `ListenerBase`) so
its address stays valid until `removeEventListener`.

The example registers `OnEchoFired` and receives a typed `EchoEvent` when Echo
fires it. Verified end-to-end and ASAN-clean.

With this the native C++ generator covers the full surface: requests
(scalar/string/bool/seq/Option/nested), typed struct returns, and typed events.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant