From 3129fa9a03f4190bbc1804e66ece6385a03356d7 Mon Sep 17 00:00:00 2001 From: gmega Date: Fri, 6 Feb 2026 16:04:16 -0300 Subject: [PATCH] remove callbacks and modify return types of synchronous calls --- examples/c/storage.c | 16 ++--------- library/README.md | 17 ++++++------ library/libstorage.h | 21 +++++++------- library/libstorage.nim | 62 ++++++++++++++++-------------------------- 4 files changed, 45 insertions(+), 71 deletions(-) diff --git a/examples/c/storage.c b/examples/c/storage.c index 4ae34b42..cbe32ae9 100644 --- a/examples/c/storage.c +++ b/examples/c/storage.c @@ -290,19 +290,9 @@ int cleanup(void *storage_ctx) int check_version(void *storage_ctx) { - char *res = NULL; - - Resp *r = alloc_resp(); - - // No need to wait here as storage_version is synchronous - if (storage_version(storage_ctx, (StorageCallback)callback, r) != RET_OK) - { - free_resp(r); - return RET_ERR; - } - - free_resp(r); - + char *version = storage_version(storage_ctx); + printf("version: %s\n", version); + free(version); return RET_OK; } diff --git a/library/README.md b/library/README.md index 7b15851e..b9fd0567 100644 --- a/library/README.md +++ b/library/README.md @@ -137,10 +137,11 @@ int storage_close(void *ctx, StorageCallback callback, void *userData); ### `storage_destroy` -Destroy the node instance and free associated resources. Node must be stopped and closed. +Destroys the node instance and frees associated resources. Node must be stopped and closed. +The call is synchronous, so it does not require a callback. ```c -int storage_destroy(void *ctx, StorageCallback callback, void *userData); +int storage_destroy(void *ctx); ``` --- @@ -149,22 +150,22 @@ int storage_destroy(void *ctx, StorageCallback callback, void *userData); ### `storage_version` -Get the Logos Storage version string. -Does not require the node to be started and does not involve a thread call. +Get the Logos Storage version as a null-terminated string. The caller is responsible for freeing it. +Does not require the node to be started. It is also a synchronous call, so it does not require a callback. ```c -int storage_version(void *ctx, StorageCallback callback, void *userData); +char* storage_version(void *ctx); ``` --- ### `storage_revision` -Get the Logos Storage contracts revision. -Does not require the node to be started and does not involve a thread call. +Get the Logos Storage contracts revision as a null-terminated string. The caller is responsible for freeing it. +Does not require the node to be started. It is also a synchronous call, so it does not require a callback. ```c -int storage_revision(void *ctx, StorageCallback callback, void *userData); +char* storage_revision(void *ctx); ``` --- diff --git a/library/libstorage.h b/library/libstorage.h index 458cd313..daa14d57 100644 --- a/library/libstorage.h +++ b/library/libstorage.h @@ -64,18 +64,18 @@ extern "C" // Get the Logos Storage version string. // This call does not require the node to be started and // does not involve a thread call. - int storage_version( - void *ctx, - StorageCallback callback, - void *userData); + // It is also synchronous, so it does not require a callback. + // Returns a null-terminated string which needs to be deallocated + // by the caller. + char *storage_version(void *ctx); // Get the Logos Storage contracts revision. // This call does not require the node to be started and // does not involve a thread call. - int storage_revision( - void *ctx, - StorageCallback callback, - void *userData); + // It is also synchronous, so it does not require a callback. + // Returns a null-terminated string which needs to be deallocated + // by the caller. + char *storage_revision(void *ctx); // Get the repo (data-dir) used by the node. int storage_repo( @@ -375,6 +375,7 @@ extern "C" // Destroys an instance of a Logos Storage node. // This will free all resources associated with the node. // The node must be stopped and closed before calling this function. + // The call is synchronous, so it does not require a callback. // // Typical usage: // ctx = storage_new(configJson, myCallback, myUserData); @@ -383,9 +384,7 @@ extern "C" // storage_stop(ctx, ...); // storage_close(ctx, ...); // storage_destroy(ctx, ...); - int storage_destroy(void *ctx, - StorageCallback callback, - void *userData); + int storage_destroy(void *ctx); // Not used currently. // Reserved for future use to set an event callback. diff --git a/library/libstorage.nim b/library/libstorage.nim index a1a71108..46f0749c 100644 --- a/library/libstorage.nim +++ b/library/libstorage.nim @@ -8,15 +8,15 @@ # - Thread-safe exported procs callable from C # - Callback registration and invocation for asynchronous communication -# cdecl is C declaration calling convention. +# cdecl is C declaration calling convention. # It’s the standard way C compilers expect functions to behave: -# 1- Caller cleans up the stack after the call +# 1- Caller cleans up the stack after the call # 2- Symbol names are exported in a predictable way # In other termes, it is a glue that makes Nim functions callable as normal C functions. {.pragma: exported, exportc, cdecl, raises: [].} {.pragma: callback, cdecl, raises: [], gcsafe.} -# Ensure code is position-independent so it can be built into a shared library (.so). +# Ensure code is position-independent so it can be built into a shared library (.so). # In other terms, the code that can run no matter where it’s placed in memory. {.passc: "-fPIC".} @@ -53,7 +53,19 @@ template checkLibstorageParams*( if isNil(callback): return RET_MISSING_CALLBACK -# From Nim doc: +proc malloc(size: csize_t): pointer {.importc, header: "".} + +proc asNewCString(s: string): ptr cchar = + # We need malloc so C clients can free it. + let + n = s.len + cstr = cast[ptr UncheckedArray[cchar]](malloc(n.csize_t + 1)) + if n > 0: + copyMem(cstr, addr s[0], n) + cstr[n] = 0.cchar + cast[ptr cchar](cstr) + +# From Nim doc: # "the C targets require you to initialize Nim's internals, which is done calling a NimMain function." # "The name NimMain can be influenced via the --nimMainPrefix:prefix switch." # "Use --nimMainPrefix:MyLib and the function to call is named MyLibNimMain." @@ -110,35 +122,15 @@ proc storage_new( return ctx -proc storage_version( - ctx: ptr StorageContext, callback: StorageCallback, userData: pointer -): cint {.dynlib, exportc.} = +proc storage_version(ctx: ptr StorageContext): ptr cchar {.dynlib, exportc.} = initializeLibrary() - checkLibstorageParams(ctx, callback, userData) - callback( - RET_OK, - cast[ptr cchar](conf.codexVersion), - cast[csize_t](len(conf.codexVersion)), - userData, - ) + return asNewCString(conf.codexVersion) - return RET_OK - -proc storage_revision( - ctx: ptr StorageContext, callback: StorageCallback, userData: pointer -): cint {.dynlib, exportc.} = +proc storage_revision(ctx: ptr StorageContext): ptr cchar {.dynlib, exportc.} = initializeLibrary() - checkLibstorageParams(ctx, callback, userData) - callback( - RET_OK, - cast[ptr cchar](conf.codexRevision), - cast[csize_t](len(conf.codexRevision)), - userData, - ) - - return RET_OK + return asNewCString(conf.codexRevision) proc storage_repo( ctx: ptr StorageContext, callback: StorageCallback, userData: pointer @@ -268,18 +260,10 @@ proc storage_close( return callback.okOrError(res, userData) -proc storage_destroy( - ctx: ptr StorageContext, callback: StorageCallback, userData: pointer -): cint {.dynlib, exportc.} = +proc storage_destroy(ctx: ptr StorageContext): cint {.dynlib, exportc.} = initializeLibrary() - checkLibstorageParams(ctx, callback, userData) - - let - res = storage_context.destroyStorageContext(ctx) - ret = if res.isErr: RET_ERR else: RET_OK - - callback(ret, nil, 0, userData) - return ret + let res = storage_context.destroyStorageContext(ctx) + if res.isErr: RET_ERR else: RET_OK proc storage_upload_init( ctx: ptr StorageContext,