kglite-c 0.14.2

C ABI for kglite — stable extern "C" surface over the kglite engine so non-Rust bindings (Go via cgo, JavaScript via napi, JVM via JNI, .NET via P/Invoke, …) consume a single C header rather than re-implementing wrappers in their host language. The Rust types (DirGraph, Session, CypherResult, KgErrorCode) live in the sibling `kglite` crate; this crate is glue.
Documentation

kglite-c — C ABI for KGLite

kglite-c is the supported C boundary for non-Rust bindings such as cgo, napi, JNI, P/Invoke, and Swift FFI. The pure-Rust engine owns Cypher, storage, sessions, and persistence; this crate exposes a curated synchronous ABI through the generated include/kglite.h.

The generated header is the exact symbol, signature, status, and ownership authority. Header drift is checked in CI. Precompiled C ABI libraries are not currently attached to releases, so build and package the matching source for each target platform:

cargo build -p kglite-c --release

Minimal C example

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

int main(void) {
    KgliteGraph *graph = NULL;
    const char *error = NULL;
    KgliteStatusCode status = kglite_load_file("graph.kgl", &graph, &error);
    if (status != KGLITE_STATUS_CODE_OK) {
        fprintf(stderr, "%s\n", error ? error : "load failed");
        kglite_free_string(error);
        return 1;
    }

    KgliteSession *session = NULL;
    status = kglite_session_new(graph, &session); /* moves graph ownership */
    if (status != KGLITE_STATUS_CODE_OK) {
        kglite_graph_free(graph);
        return 1;
    }

    KgliteCypherResult *result = NULL;
    status = kglite_session_execute_read(
        session,
        "MATCH (n) RETURN count(n) AS count",
        NULL,
        &result,
        &error
    );
    if (status != KGLITE_STATUS_CODE_OK) {
        fprintf(stderr, "%s\n", error ? error : "query failed");
        kglite_free_string(error);
        kglite_session_free(session);
        return 1;
    }

    const char *rows = kglite_cypher_result_rows_json(result);
    printf("%s\n", rows);
    kglite_free_string(rows);
    kglite_cypher_result_free(result);
    kglite_session_free(session);
    return 0;
}

Ownership

  • Input pointers are borrowed for the duration of the call.
  • A successful kglite_session_new takes ownership of its graph handle.
  • Opaque result/session/graph/embedder handles use their matching *_free function.
  • Every returned Rust-owned string uses kglite_free_string exactly once.
  • Null-safe free calls are allowed; double-free and foreign-allocator pointers are not.

Fallible calls reset non-null output slots before validation. Valid calls that panic inside Rust are contained and reported as KGLITE_STATUS_CODE_INTERNAL; dangling or invalid caller pointers remain outside the ABI contract.

Errors and runtime model

KgliteStatusCode contains engine status codes 1–17 plus boundary-only 100+ codes for conditions such as invalid UTF-8 and null pointers. Preserve the code and message separately; do not classify failures by parsing text. The ABI is synchronous, so each binding owns async scheduling, logging, display, and teardown conventions.

Versioning

kglite-c follows the workspace version. kglite_abi_version() reports the linked runtime version, and the .kgl reader/writer follows the engine's saved format lifecycle. See the C ABI guide and binding guide.

License

MIT, matching the KGLite workspace.