Ivan FB a3e68333ab
refactor(codegen): reconcile C++ header names with the native/cbor convention
Aligns the C++ generators with the C generator and the symbol naming: the
native (zero-serialization, same-process) wrapper is the bare `<lib>.hpp` and
the CBOR (inter-process) wrapper carries the `_cbor` suffix — mirroring the C
headers (`<lib>.h` / `<lib>_cbor.h`) and the `<name>` / `<name>_cbor` exports.

Previously native was `<lib>_native.hpp` and CBOR was the bare `<lib>.hpp`,
which is backwards from the symbol convention and would collide on the native
`<lib>.h` when both ABIs emit into one dir (ffiMode=both). With the flip, a
single `genbindings_cpp` run now drops `<lib>.hpp` + `<lib>_cbor.hpp` side by
side, exactly like c_bindings holds both `.h` headers.

Consumers updated to match: the CBOR cpp_bindings driver and the C++ e2e suite
include `*_cbor.hpp`; the native example includes the bare `<lib>.hpp`.

Validated: native example runs on `my_timer.hpp`; C++ e2e suite 19/19 on the
`_cbor.hpp` headers; check_bindings_cpp regen is deterministic.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 19:31:39 +02:00

158 lines
4.4 KiB
C++

// Generated by nim-ffi native C++ codegen. Do not edit by hand.
//
// Native (zero-serialization) wrapper over the C ABI in "echo.h". Struct params/returns cross as flat C-POD structs — no CBOR. For the
// inter-process path use the CBOR header (echo_cbor.hpp).
#ifndef NIM_FFI_GEN_ECHO_NATIVE_HPP
#define NIM_FFI_GEN_ECHO_NATIVE_HPP
#include "echo.h"
#include <cstdint>
#include <functional>
#include <future>
#include <map>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <vector>
namespace echo {
struct EchoConfig {
std::string prefix{};
};
struct EchoConfigC {
::EchoConfig c{};
};
inline EchoConfigC toC(const EchoConfig& v) {
EchoConfigC h;
h.c.prefix = v.prefix.c_str();
return h;
}
inline EchoConfig fromC(const ::EchoConfig& c) {
EchoConfig v{};
v.prefix = c.prefix ? std::string(c.prefix) : std::string();
return v;
}
struct ShoutRequest {
std::string text{};
};
struct ShoutRequestC {
::ShoutRequest c{};
};
inline ShoutRequestC toC(const ShoutRequest& v) {
ShoutRequestC h;
h.c.text = v.text.c_str();
return h;
}
inline ShoutRequest fromC(const ::ShoutRequest& c) {
ShoutRequest v{};
v.text = c.text ? std::string(c.text) : std::string();
return v;
}
struct ShoutResponse {
std::string shouted{};
std::string prefix{};
};
struct ShoutResponseC {
::ShoutResponse c{};
};
inline ShoutResponseC toC(const ShoutResponse& v) {
ShoutResponseC h;
h.c.shouted = v.shouted.c_str();
h.c.prefix = v.prefix.c_str();
return h;
}
inline ShoutResponse fromC(const ::ShoutResponse& c) {
ShoutResponse v{};
v.shouted = c.shouted ? std::string(c.shouted) : std::string();
v.prefix = c.prefix ? std::string(c.prefix) : std::string();
return v;
}
namespace detail {
template <typename T> struct Capture {
int ret = RET_ERR;
T value{};
std::string err;
std::promise<void> done;
};
struct AckCapture {
int ret = RET_ERR;
std::string err;
std::promise<void> done;
};
inline std::string rawText(const char* msg, std::size_t len) {
return (msg && len) ? std::string(msg, len) : std::string();
}
} // namespace detail
extern "C" {
inline void echo_native_ack(int ret, const char* msg, std::size_t len, void* ud) {
auto* c = static_cast<detail::AckCapture*>(ud);
c->ret = ret;
if (ret == RET_ERR) c->err = detail::rawText(msg, len);
c->done.set_value();
}
inline void echo_native_str(int ret, const char* msg, std::size_t len, void* ud) {
auto* c = static_cast<detail::Capture<std::string>*>(ud);
c->ret = ret;
if (ret == RET_OK) c->value = detail::rawText(msg, len);
else c->err = detail::rawText(msg, len);
c->done.set_value();
}
inline void echo_native_echo_shout(int ret, const char* msg, std::size_t len, void* ud) {
auto* c = static_cast<detail::Capture<ShoutResponse>*>(ud);
c->ret = ret;
if (ret == RET_OK) c->value = fromC(*reinterpret_cast<const ::ShoutResponse*>(msg));
else c->err = detail::rawText(msg, len);
c->done.set_value();
}
} // extern "C"
class EchoNode {
public:
explicit EchoNode(const EchoConfig& config) {
detail::AckCapture cap;
auto fut = cap.done.get_future();
auto c_config = toC(config);
ctx_ = echo_create(c_config.c, echo_native_ack, &cap);
if (!ctx_) throw std::runtime_error("echo_create returned null");
fut.wait();
if (cap.ret != RET_OK) throw std::runtime_error(cap.err);
}
ShoutResponse Shout(const ShoutRequest& req) {
detail::Capture<ShoutResponse> cap;
auto fut = cap.done.get_future();
auto c_req = toC(req);
if (echo_shout(ctx_, echo_native_echo_shout, &cap, c_req.c) != RET_OK)
throw std::runtime_error("echo_shout dispatch failed");
fut.wait();
if (cap.ret != RET_OK) throw std::runtime_error(cap.err);
return cap.value;
}
std::string Version() {
detail::Capture<std::string> cap;
auto fut = cap.done.get_future();
if (echo_version(ctx_, echo_native_str, &cap) != RET_OK)
throw std::runtime_error("echo_version dispatch failed");
fut.wait();
if (cap.ret != RET_OK) throw std::runtime_error(cap.err);
return cap.value;
}
~EchoNode() { if (ctx_) echo_destroy(ctx_); }
EchoNode(const EchoNode&) = delete;
EchoNode& operator=(const EchoNode&) = delete;
private:
void* ctx_ = nullptr;
};
} // namespace echo
#endif // NIM_FFI_GEN_ECHO_NATIVE_HPP