// Code generated by nim-ffi Go codegen. DO NOT EDIT. package my_timer /* #cgo CFLAGS: -I${SRCDIR} #cgo LDFLAGS: -L${SRCDIR} -lmy_timer -Wl,-rpath,${SRCDIR} #include "my_timer.h" #include #include #include extern void my_timerGoEvent(int ret, char* msg, size_t len, void* userData); typedef struct { int ret; char* msg; size_t len; int done; pthread_mutex_t mu; pthread_cond_t cv; } My_timerResp; static My_timerResp* my_timerRespNew() { My_timerResp* r = (My_timerResp*)calloc(1, sizeof(My_timerResp)); pthread_mutex_init(&r->mu, NULL); pthread_cond_init(&r->cv, NULL); return r; } static void my_timerRespFree(My_timerResp* r) { if (!r) return; if (r->msg) free(r->msg); pthread_mutex_destroy(&r->mu); pthread_cond_destroy(&r->cv); free(r); } static int my_timerRespRet(My_timerResp* r) { return r->ret; } static char* my_timerRespMsg(My_timerResp* r) { return r->msg; } static size_t my_timerRespLen(My_timerResp* r) { return r->len; } static void my_timerRespCb(int ret, const char* msg, size_t len, void* ud) { My_timerResp* r = (My_timerResp*)ud; pthread_mutex_lock(&r->mu); r->ret = ret; // Native ABI: (msg, len) is the raw result (RET_OK) or error (RET_ERR). // Copy it so it survives past the callback. char* e = (char*)malloc(len + 1); if (e) { memcpy(e, msg, len); e[len] = 0; } r->msg = e; r->len = len; r->done = 1; pthread_cond_signal(&r->cv); pthread_mutex_unlock(&r->mu); } static void my_timerRespWait(My_timerResp* r) { pthread_mutex_lock(&r->mu); while (!r->done) pthread_cond_wait(&r->cv, &r->mu); pthread_mutex_unlock(&r->mu); } static void* my_timerCall_my_timer_create(TimerConfig config, My_timerResp* r) { void* ctx = my_timer_create(config, my_timerRespCb, r); my_timerRespWait(r); return ctx; } static int my_timerCall_my_timer_echo(void* ctx, EchoRequest req, My_timerResp* r) { int rc = my_timer_echo(ctx, my_timerRespCb, r, req); if (rc == RET_OK) my_timerRespWait(r); return rc; } static int my_timerCall_my_timer_version(void* ctx, My_timerResp* r) { int rc = my_timer_version(ctx, my_timerRespCb, r); if (rc == RET_OK) my_timerRespWait(r); return rc; } static int my_timerCall_my_timer_complex(void* ctx, ComplexRequest req, My_timerResp* r) { int rc = my_timer_complex(ctx, my_timerRespCb, r, req); if (rc == RET_OK) my_timerRespWait(r); return rc; } static int my_timerCall_my_timer_schedule(void* ctx, JobSpec job, RetryPolicy retry, ScheduleConfig schedule, My_timerResp* r) { int rc = my_timer_schedule(ctx, my_timerRespCb, r, job, retry, schedule); if (rc == RET_OK) my_timerRespWait(r); return rc; } static int my_timerCall_my_timer_destroy(void* ctx) { return my_timer_destroy(ctx); } static uint64_t my_timerRegisterEvents(void* ctx) { return my_timer_add_event_listener(ctx, "", (FFICallBack)my_timerGoEvent, ctx); } */ import "C" import ( "errors" "sync" "unsafe" ) // TimerConfig mirrors the {.ffi.} type of the same name. type TimerConfig struct { Name string } // toC marshals TimerConfig into its C-POD form, returning cleanup funcs to run after the call. func (v TimerConfig) toC() (C.TimerConfig, []func()) { var c C.TimerConfig var frees []func() cs_name := C.CString(v.Name) frees = append(frees, func() { C.free(unsafe.Pointer(cs_name)) }) c.name = cs_name return c, frees } // EchoRequest mirrors the {.ffi.} type of the same name. type EchoRequest struct { Message string DelayMs int64 } // toC marshals EchoRequest into its C-POD form, returning cleanup funcs to run after the call. func (v EchoRequest) toC() (C.EchoRequest, []func()) { var c C.EchoRequest var frees []func() cs_message := C.CString(v.Message) frees = append(frees, func() { C.free(unsafe.Pointer(cs_message)) }) c.message = cs_message c.delayMs = C.int64_t(v.DelayMs) return c, frees } // EchoResponse mirrors the {.ffi.} type of the same name. type EchoResponse struct { Echoed string TimerName string } // toC marshals EchoResponse into its C-POD form, returning cleanup funcs to run after the call. func (v EchoResponse) toC() (C.EchoResponse, []func()) { var c C.EchoResponse var frees []func() cs_echoed := C.CString(v.Echoed) frees = append(frees, func() { C.free(unsafe.Pointer(cs_echoed)) }) c.echoed = cs_echoed cs_timerName := C.CString(v.TimerName) frees = append(frees, func() { C.free(unsafe.Pointer(cs_timerName)) }) c.timerName = cs_timerName return c, frees } // ComplexRequest mirrors the {.ffi.} type of the same name. type ComplexRequest struct { Messages []EchoRequest Tags []string Note *string Retries *int64 } // toC marshals ComplexRequest into its C-POD form, returning cleanup funcs to run after the call. func (v ComplexRequest) toC() (C.ComplexRequest, []func()) { var c C.ComplexRequest var frees []func() if n_messages := len(v.Messages); n_messages > 0 { arr_messages := C.malloc(C.size_t(n_messages) * C.size_t(unsafe.Sizeof(C.EchoRequest{}))) sl_messages := unsafe.Slice((*C.EchoRequest)(arr_messages), n_messages) for i := 0; i < n_messages; i++ { cf_messages_e, ff_messages_e := (v.Messages[i]).toC() frees = append(frees, ff_messages_e...) sl_messages[i] = cf_messages_e } c.messages = (*C.EchoRequest)(arr_messages) c.messages_len = C.size_t(n_messages) a_messages := arr_messages frees = append(frees, func() { C.free(a_messages) }) } if n_tags := len(v.Tags); n_tags > 0 { arr_tags := C.malloc(C.size_t(n_tags) * C.size_t(unsafe.Sizeof((*C.char)(nil)))) sl_tags := unsafe.Slice((**C.char)(arr_tags), n_tags) for i := 0; i < n_tags; i++ { cs_tags_e := C.CString(v.Tags[i]) frees = append(frees, func() { C.free(unsafe.Pointer(cs_tags_e)) }) sl_tags[i] = cs_tags_e } c.tags = (**C.char)(arr_tags) c.tags_len = C.size_t(n_tags) a_tags := arr_tags frees = append(frees, func() { C.free(a_tags) }) } if v.Note != nil { c.note_present = 1 cs_note_o := C.CString(*v.Note) frees = append(frees, func() { C.free(unsafe.Pointer(cs_note_o)) }) c.note = cs_note_o } if v.Retries != nil { c.retries_present = 1 c.retries = C.int64_t(*v.Retries) } return c, frees } // ComplexResponse mirrors the {.ffi.} type of the same name. type ComplexResponse struct { Summary string ItemCount int64 HasNote bool } // toC marshals ComplexResponse into its C-POD form, returning cleanup funcs to run after the call. func (v ComplexResponse) toC() (C.ComplexResponse, []func()) { var c C.ComplexResponse var frees []func() cs_summary := C.CString(v.Summary) frees = append(frees, func() { C.free(unsafe.Pointer(cs_summary)) }) c.summary = cs_summary c.itemCount = C.int64_t(v.ItemCount) if v.HasNote { c.hasNote = 1 } else { c.hasNote = 0 } return c, frees } // EchoEvent mirrors the {.ffi.} type of the same name. type EchoEvent struct { Message string EchoCount int64 } // toC marshals EchoEvent into its C-POD form, returning cleanup funcs to run after the call. func (v EchoEvent) toC() (C.EchoEvent, []func()) { var c C.EchoEvent var frees []func() cs_message := C.CString(v.Message) frees = append(frees, func() { C.free(unsafe.Pointer(cs_message)) }) c.message = cs_message c.echoCount = C.int64_t(v.EchoCount) return c, frees } // JobSpec mirrors the {.ffi.} type of the same name. type JobSpec struct { Name string Payload []string Priority int64 } // toC marshals JobSpec into its C-POD form, returning cleanup funcs to run after the call. func (v JobSpec) toC() (C.JobSpec, []func()) { var c C.JobSpec var frees []func() cs_name := C.CString(v.Name) frees = append(frees, func() { C.free(unsafe.Pointer(cs_name)) }) c.name = cs_name if n_payload := len(v.Payload); n_payload > 0 { arr_payload := C.malloc(C.size_t(n_payload) * C.size_t(unsafe.Sizeof((*C.char)(nil)))) sl_payload := unsafe.Slice((**C.char)(arr_payload), n_payload) for i := 0; i < n_payload; i++ { cs_payload_e := C.CString(v.Payload[i]) frees = append(frees, func() { C.free(unsafe.Pointer(cs_payload_e)) }) sl_payload[i] = cs_payload_e } c.payload = (**C.char)(arr_payload) c.payload_len = C.size_t(n_payload) a_payload := arr_payload frees = append(frees, func() { C.free(a_payload) }) } c.priority = C.int64_t(v.Priority) return c, frees } // RetryPolicy mirrors the {.ffi.} type of the same name. type RetryPolicy struct { MaxAttempts int64 BackoffMs int64 RetryOn []string } // toC marshals RetryPolicy into its C-POD form, returning cleanup funcs to run after the call. func (v RetryPolicy) toC() (C.RetryPolicy, []func()) { var c C.RetryPolicy var frees []func() c.maxAttempts = C.int64_t(v.MaxAttempts) c.backoffMs = C.int64_t(v.BackoffMs) if n_retryOn := len(v.RetryOn); n_retryOn > 0 { arr_retryOn := C.malloc(C.size_t(n_retryOn) * C.size_t(unsafe.Sizeof((*C.char)(nil)))) sl_retryOn := unsafe.Slice((**C.char)(arr_retryOn), n_retryOn) for i := 0; i < n_retryOn; i++ { cs_retryOn_e := C.CString(v.RetryOn[i]) frees = append(frees, func() { C.free(unsafe.Pointer(cs_retryOn_e)) }) sl_retryOn[i] = cs_retryOn_e } c.retryOn = (**C.char)(arr_retryOn) c.retryOn_len = C.size_t(n_retryOn) a_retryOn := arr_retryOn frees = append(frees, func() { C.free(a_retryOn) }) } return c, frees } // ScheduleConfig mirrors the {.ffi.} type of the same name. type ScheduleConfig struct { StartAtMs int64 IntervalMs int64 Jitter *int64 } // toC marshals ScheduleConfig into its C-POD form, returning cleanup funcs to run after the call. func (v ScheduleConfig) toC() (C.ScheduleConfig, []func()) { var c C.ScheduleConfig var frees []func() c.startAtMs = C.int64_t(v.StartAtMs) c.intervalMs = C.int64_t(v.IntervalMs) if v.Jitter != nil { c.jitter_present = 1 c.jitter = C.int64_t(*v.Jitter) } return c, frees } // ScheduleResult mirrors the {.ffi.} type of the same name. type ScheduleResult struct { JobId string WillRunCount int64 FirstRunAtMs int64 EffectiveBackoffMs int64 } // toC marshals ScheduleResult into its C-POD form, returning cleanup funcs to run after the call. func (v ScheduleResult) toC() (C.ScheduleResult, []func()) { var c C.ScheduleResult var frees []func() cs_jobId := C.CString(v.JobId) frees = append(frees, func() { C.free(unsafe.Pointer(cs_jobId)) }) c.jobId = cs_jobId c.willRunCount = C.int64_t(v.WillRunCount) c.firstRunAtMs = C.int64_t(v.FirstRunAtMs) c.effectiveBackoffMs = C.int64_t(v.EffectiveBackoffMs) return c, frees } type My_timerNode struct { ctx unsafe.Pointer } // goStr extracts and frees the captured response string. func respStr(r *C.My_timerResp) string { return C.GoStringN(C.my_timerRespMsg(r), C.int(C.my_timerRespLen(r))) } var ( eventMu sync.Mutex eventHandler func(string) ) // SetEventHandler installs the catch-all handler for library-initiated // events (delivered as raw JSON strings). func (n *My_timerNode) SetEventHandler(h func(string)) { eventMu.Lock() eventHandler = h eventMu.Unlock() C.my_timerRegisterEvents(n.ctx) } //export my_timerGoEvent func my_timerGoEvent(ret C.int, msg *C.char, length C.size_t, userData unsafe.Pointer) { eventMu.Lock() h := eventHandler eventMu.Unlock() if h != nil && ret == C.RET_OK { h(C.GoStringN(msg, C.int(length))) } } func NewMy_timer(config TimerConfig) (*My_timerNode, error) { c_config, free_config := config.toC() defer func() { for _, f := range free_config { f() } }() r := C.my_timerRespNew() defer C.my_timerRespFree(r) ctx := C.my_timerCall_my_timer_create(c_config, r) if C.my_timerRespRet(r) != C.RET_OK { return nil, errors.New(respStr(r)) } return &My_timerNode{ctx: ctx}, nil } func (n *My_timerNode) Echo(req EchoRequest) (string, error) { c_req, free_req := req.toC() defer func() { for _, f := range free_req { f() } }() r := C.my_timerRespNew() defer C.my_timerRespFree(r) C.my_timerCall_my_timer_echo(n.ctx, c_req, r) if C.my_timerRespRet(r) != C.RET_OK { return "", errors.New(respStr(r)) } return respStr(r), nil } func (n *My_timerNode) Version() (string, error) { r := C.my_timerRespNew() defer C.my_timerRespFree(r) C.my_timerCall_my_timer_version(n.ctx, r) if C.my_timerRespRet(r) != C.RET_OK { return "", errors.New(respStr(r)) } return respStr(r), nil } func (n *My_timerNode) Complex(req ComplexRequest) (string, error) { c_req, free_req := req.toC() defer func() { for _, f := range free_req { f() } }() r := C.my_timerRespNew() defer C.my_timerRespFree(r) C.my_timerCall_my_timer_complex(n.ctx, c_req, r) if C.my_timerRespRet(r) != C.RET_OK { return "", errors.New(respStr(r)) } return respStr(r), nil } func (n *My_timerNode) Schedule(job JobSpec, retry RetryPolicy, schedule ScheduleConfig) (string, error) { c_job, free_job := job.toC() defer func() { for _, f := range free_job { f() } }() c_retry, free_retry := retry.toC() defer func() { for _, f := range free_retry { f() } }() c_schedule, free_schedule := schedule.toC() defer func() { for _, f := range free_schedule { f() } }() r := C.my_timerRespNew() defer C.my_timerRespFree(r) C.my_timerCall_my_timer_schedule(n.ctx, c_job, c_retry, c_schedule, r) if C.my_timerRespRet(r) != C.RET_OK { return "", errors.New(respStr(r)) } return respStr(r), nil } func (n *My_timerNode) Destroy() error { if C.my_timerCall_my_timer_destroy(n.ctx) != C.RET_OK { return errors.New("my_timer destroy failed") } return nil }