Ivan FB 047b709c55
feat: generate the C header instead of hand-writing it
The hand-written liblogosdelivery.h / _kernel.h declared the pre-CBOR
string ABI, so they lied about the real one -- a C consumer would link
against signatures that no longer exist. genBindings already produces the
Rust bindings from the Nim source; this adds the C target on the same
footing.

liblogosdeliveryGenBindingsC emits library/c_bindings/: logosdelivery.h
covering the whole surface (messaging, channels and the waku_* kernel
procs in one file), plus the nim_ffi_cbor.h / _prelude.h helpers that
marshal the CBOR payloads. Params ride as CBOR blobs, matching the
library's default ABI and what the Rust crate does internally; the typed
C ABI (abi=c) stays available per-proc for later.

The two hand-written headers are deleted and nix packaging ships the
generated ones. The C examples target the old string ABI and removed
headers, so they no longer compile; each is annotated as awaiting a port
rather than left with a dangling include that pretends to work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 11:33:20 +02:00
..
2026-06-25 09:27:01 +02:00

Logos Messaging API (LMAPI) Library

A C FFI library providing a simplified interface to Logos Messaging functionality.

Overview

This library wraps the high-level API functions from waku/api/api.nim and exposes them via a C FFI interface, making them accessible from C, C++, and other languages that support C FFI.

API Functions

Node Lifecycle

logosdelivery_create_node

Creates a new instance of the node from the given configuration JSON.

void *logosdelivery_create_node(
    const char *configJson,
    FFICallBack callback,
    void *userData
);

Parameters:

  • configJson: JSON string containing node configuration
  • callback: Callback function to receive the result
  • userData: User data passed to the callback

Returns: Pointer to the context needed by other API functions, or NULL on error.

Example configuration JSON:

{
  "mode": "Core",
  "preset": "logos.dev",
  "messagingOverrides": {
    "listen-address": "0.0.0.0",
    "tcp-port": 60000,
    "discv5-udp-port": 9000
  }
}

The configuration object has four optional top-level keys: mode ("Core" or "Edge", defaults to "Core"), preset, messagingOverrides (per-field node config overrides), and channelsOverrides (reliable-channel overrides). Override keys accept the config field name or its CLI switch name (e.g. "clusterId" or "cluster-id"); unknown keys are rejected. Use "preset" to select a network preset (e.g., "twn", "logos.dev", "status.prod") which auto-configures entry nodes, cluster ID, sharding, and other network-specific settings.

Available presets:

Preset Cluster ID RLN Sharding Network
twn 1 on auto (8 shards) The Waku Network
logos.dev 2 off auto (8 shards) Logos Dev Network
logos.test 2 off auto (8 shards) Logos Test Network
status.prod 16 off auto (1 shard) Status Production Network

logosdelivery_start_node

Starts the node.

int logosdelivery_start_node(
    void *ctx,
    FFICallBack callback,
    void *userData
);

logosdelivery_stop_node

Stops the node.

int logosdelivery_stop_node(
    void *ctx,
    FFICallBack callback,
    void *userData
);

logosdelivery_destroy

Destroys a node instance and frees resources.

int logosdelivery_destroy(
    void *ctx,
    FFICallBack callback,
    void *userData
);

Messaging

logosdelivery_subscribe

Subscribe to a content topic to receive messages.

int logosdelivery_subscribe(
    void *ctx,
    FFICallBack callback,
    void *userData,
    const char *contentTopic
);

Parameters:

  • ctx: Context pointer from logosdelivery_create_node
  • callback: Callback function to receive the result
  • userData: User data passed to the callback
  • contentTopic: Content topic string (e.g., "/myapp/1/chat/proto")

logosdelivery_unsubscribe

Unsubscribe from a content topic.

int logosdelivery_unsubscribe(
    void *ctx,
    FFICallBack callback,
    void *userData,
    const char *contentTopic
);

logosdelivery_send

Send a message.

int logosdelivery_send(
    void *ctx,
    FFICallBack callback,
    void *userData,
    const char *messageJson
);

Parameters:

  • messageJson: JSON string containing the message

Example message JSON:

{
  "contentTopic": "/myapp/1/chat/proto",
  "payload": "SGVsbG8gV29ybGQ=",
  "ephemeral": false
}

Note: The payload field should be base64-encoded.

Returns: Request ID in the callback message that can be used to track message delivery.

Events

logosdelivery_add_event_listener

Registers a callback invoked whenever the named event fires (e.g., message received). Listeners are registered per event name, so register once for each event you want to observe.

uint64_t logosdelivery_add_event_listener(
    void *ctx,
    const char *eventName,
    FFICallBack callback,
    void *userData
);

Returns: The listener id (> 0), or 0 if callback is NULL.

Event names: onMessageSent, onMessageError, onMessagePropagated, onMessageReceived, onConnectionStatusChange, onTopicHealthChange, onConnectionChange, onChannelMessageReceived, onChannelMessageSent, onChannelMessageError, onReceivedMessage.

logosdelivery_remove_event_listener

Unregisters a previously added listener.

int logosdelivery_remove_event_listener(
    void *ctx,
    uint64_t listenerId
);

Returns: RET_OK when a listener was removed, RET_ERR otherwise.

Important: The callback should be fast, non-blocking, and thread-safe.

Building

The library follows the same build system as the main Logos Messaging project.

Build the library

make liblogosdeliveryStatic    # Build static library
# or
make liblogosdeliveryDynamic   # Build dynamic library

Return Codes

All functions that return int use the following return codes:

  • RET_OK (0): Success
  • RET_ERR (1): Error
  • RET_MISSING_CALLBACK (2): Missing callback function

Callback Function

All API functions use the following callback signature:

typedef void (*FFICallBack)(
    int callerRet,
    const char *msg,
    size_t len,
    void *userData
);

Parameters:

  • callerRet: Return code (RET_OK, RET_ERR, etc.)
  • msg: Response message (may be empty for success)
  • len: Length of the message
  • userData: User data passed in the original call

Example Usage

#include "liblogosdelivery.h"
#include <stdio.h>

void callback(int ret, const char *msg, size_t len, void *userData) {
    if (ret == RET_OK) {
        printf("Success: %.*s\n", (int)len, msg);
    } else {
        printf("Error: %.*s\n", (int)len, msg);
    }
}

int main() {
    const char *config = "{"
        "\"logLevel\": \"INFO\","
        "\"mode\": \"Core\","
        "\"preset\": \"logos.dev\""
        "}";

    // Create node
    void *ctx = logosdelivery_create_node(config, callback, NULL);
    if (ctx == NULL) {
        return 1;
    }

    // Start node
    logosdelivery_start_node(ctx, callback, NULL);

    // Subscribe to a topic
    logosdelivery_subscribe(ctx, callback, NULL, "/myapp/1/chat/proto");

    // Send a message
    const char *msg = "{"
        "\"contentTopic\": \"/myapp/1/chat/proto\","
        "\"payload\": \"SGVsbG8gV29ybGQ=\","
        "\"ephemeral\": false"
        "}";
    logosdelivery_send(ctx, callback, NULL, msg);

    // Clean up
    logosdelivery_stop_node(ctx, callback, NULL);
    logosdelivery_destroy(ctx, callback, NULL);

    return 0;
}

Architecture

The library is structured as follows:

  • liblogosdelivery.h: C header file with function declarations
  • liblogosdelivery.nim: Main library entry point
  • declare_lib.nim: Library declaration and initialization
  • lmapi/node_api.nim: Node lifecycle API implementation
  • lmapi/messaging_api.nim: Subscribe/send API implementation

The library uses the nim-ffi framework for FFI infrastructure, which handles:

  • Thread-safe request processing
  • Async operation management
  • Memory management between C and Nim
  • Callback marshaling

See Also

  • Main API documentation: waku/api/api.nim
  • Original libwaku library: library/libwaku.nim
  • nim-ffi framework: vendor/nim-ffi/