Ivan FB 3240ac0080
feat(host): {.ffiHost.} metadata + Go wrapper (increment 5)
5a: record {.ffiHost.} procs in a compile-time registry (FFIHostMeta /
ffiHostRegistry), populated by the macro, so generators can see host fns.

5b: the Go generator emits an idiomatic wrapper over the host C ABI:
- a single //export cgo trampoline backs every host fn; a cgo.Handle in
  userData selects the Go closure;
- the closure runs on a fresh GOROUTINE so the FFI thread is never blocked
  (the non-blocking contract), then answers via <lib>_host_complete by token;
- a per-host `Set<Name>(func(string) (string, error))` method registers it.

Validated end to end with `go run` (examples/host_demo): Go UseToken -> Nim
{.ffi.} handler -> await fetchToken {.ffiHost.} -> Go trampoline -> goroutine
runs the closure -> host_complete -> future resolves on the loop thread ->
"token[TOK-session]" back in Go. Timer's Go output is unchanged (no host fns);
its regenerated .h just gains the always-exported host ABI decls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 23:49:36 +02:00

129 lines
3.4 KiB
C

// Generated by nim-ffi C codegen. Do not edit by hand.
//
// Native (zero-serialization) C ABI. Each call delivers its result to the
// callback. On RET_OK:
// - string-returning procs: (msg, len) is the raw string bytes (not
// NUL-terminated; use len).
// - struct-returning procs: msg is a pointer to the returned C struct — cast
// it to `const <Type>*` (len is sizeof). It is valid ONLY for the duration
// of the callback; copy out anything you need before returning. The library
// deep-frees it right after the callback (you free nothing).
// On RET_ERR, (msg, len) is the raw error text. A `<name>_cbor` variant of each
// proc also exists for generic/cross-language callers that prefer CBOR.
#ifndef NIM_FFI_GEN_MY_TIMER_H
#define NIM_FFI_GEN_MY_TIMER_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef NIM_FFI_RET_CODES
#define NIM_FFI_RET_CODES
#define RET_OK 0
#define RET_ERR 1
#define RET_MISSING_CALLBACK 2
#endif
#ifndef NIM_FFI_CALLBACK_T
#define NIM_FFI_CALLBACK_T
typedef void (*FFICallBack)(int callerRet, const char *msg, size_t len, void *userData);
#endif
// --- {.ffi.}-annotated types, exposed as C structs ----------
typedef struct {
const char* name;
} TimerConfig;
typedef struct {
const char* message;
int64_t delayMs;
} EchoRequest;
typedef struct {
const char* echoed;
const char* timerName;
} EchoResponse;
typedef struct {
EchoRequest *messages;
size_t messages_len;
const char* *tags;
size_t tags_len;
int note_present;
const char* note;
int retries_present;
int64_t retries;
} ComplexRequest;
typedef struct {
const char* summary;
int64_t itemCount;
int hasNote;
} ComplexResponse;
typedef struct {
const char* message;
int64_t echoCount;
} EchoEvent;
typedef struct {
const char* name;
const char* *payload;
size_t payload_len;
int64_t priority;
} JobSpec;
typedef struct {
int64_t maxAttempts;
int64_t backoffMs;
const char* *retryOn;
size_t retryOn_len;
} RetryPolicy;
typedef struct {
int64_t startAtMs;
int64_t intervalMs;
int jitter_present;
int64_t jitter;
} ScheduleConfig;
typedef struct {
const char* jobId;
int64_t willRunCount;
int64_t firstRunAtMs;
int64_t effectiveBackoffMs;
} ScheduleResult;
void *my_timer_create(TimerConfig config, FFICallBack callback, void *userData);
int my_timer_echo(void *ctx, FFICallBack callback, void *userData, EchoRequest req);
int my_timer_version(void *ctx, FFICallBack callback, void *userData);
int my_timer_complex(void *ctx, FFICallBack callback, void *userData, ComplexRequest req);
int my_timer_schedule(void *ctx, FFICallBack callback, void *userData, JobSpec job, RetryPolicy retry, ScheduleConfig schedule);
int my_timer_destroy(void *ctx);
uint64_t my_timer_add_event_listener(void *ctx, const char *eventName, FFICallBack callback, void *userData);
int my_timer_remove_event_listener(void *ctx, uint64_t listenerId);
// --- host callbacks ({.ffiHost.}) — host-implemented functions --------
#ifndef NIM_FFI_HOST_FN_T
#define NIM_FFI_HOST_FN_T
typedef void (*FFIHostFn)(uint64_t token, const char *req, size_t reqLen, void *userData);
#endif
int my_timer_register_host_fn(void *ctx, const char *name, FFIHostFn fn, void *userData);
int my_timer_host_complete(void *ctx, uint64_t token, int ret, const char *msg, size_t len);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* NIM_FFI_GEN_MY_TIMER_H */