C FFI API

The C API provides a stable ABI for embedding gridwell in any language with C interop. The header is crates/gridwell-ffi/include/gridwell.h. It is generated from the Rust source by cbindgen, and a test fails if the committed copy goes stale, so the header is the authoritative reference. The summary below mirrors it.

Types

typedef struct GridwellTable GridwellTable;   // opaque
typedef struct GridwellError GridwellError;   // opaque

typedef struct GridwellTextResult {
    char *text;     // NUL-terminated UTF-8; null on failure
    size_t len;     // bytes, excluding the terminator
} GridwellTextResult;

typedef struct GridwellBinaryResult {
    uint8_t *data;  // null on failure
    size_t len;
} GridwellBinaryResult;

Error codes

Code Constant Meaning
1 GRIDWELL_ERR_PARSE Invalid UTF-8 or JSON, or JSON that isn’t a table IR
2 GRIDWELL_ERR_VALIDATE The IR failed validation; the message lists the errors
3 GRIDWELL_ERR_RENDER A writer failed, the format name is unknown, or a binary format was passed to gridwell_render_text (or a text one to gridwell_render_binary)
4 GRIDWELL_ERR_INVALID_ARG A required pointer was null, or a string wasn’t UTF-8
5 GRIDWELL_ERR_PANIC An internal panic was caught at the boundary (always a gridwell bug; please report it)
6 GRIDWELL_ERR_OPTIONS The writer options are invalid: malformed JSON, not an object, an unknown option, a wrong type, or a value out of range

No Rust panic ever unwinds into C: each function catches panics and reports them as GRIDWELL_ERR_PANIC.

Functions

// Parse
GridwellTable *gridwell_parse_ir(const char *json, size_t len, GridwellError **err);

// Validate: null on success, else an error listing every problem.
GridwellError *gridwell_validate(const GridwellTable *table);

// Render text (html, latex, typst, rtf, svg, ansi, pandoc, quarto).
// Both render functions validate first: invalid IR returns an empty result and an
// error with code GRIDWELL_ERR_VALIDATE whose message lists the validation errors.
GridwellTextResult gridwell_render_text(
    const GridwellTable *table, const char *format, GridwellError **err);

// Render binary (docx, xlsx, pptx)
GridwellBinaryResult gridwell_render_binary(
    const GridwellTable *table, const char *format, GridwellError **err);

// The same with writer options: a JSON object, or null for the defaults.
GridwellTextResult gridwell_render_text_with_options(
    const GridwellTable *table, const char *format, const char *options,
    GridwellError **err);
GridwellBinaryResult gridwell_render_binary_with_options(
    const GridwellTable *table, const char *format, const char *options,
    GridwellError **err);

// Formats: a static comma-separated list of names (do not free), and a name's kind
// (GRIDWELL_FORMAT_TEXT, GRIDWELL_FORMAT_BINARY or GRIDWELL_FORMAT_UNKNOWN).
const char *gridwell_format_names(void);
int32_t gridwell_format_kind(const char *format);

// Error inspection
const char *gridwell_error_message(const GridwellError *err);  // valid until freed
int32_t gridwell_error_code(const GridwellError *err);         // 0 if err is null

// Memory management (all accept null / failed results)
void gridwell_free_table(GridwellTable *table);
void gridwell_free_error(GridwellError *err);
void gridwell_free_text_result(GridwellTextResult result);
void gridwell_free_binary_result(GridwellBinaryResult result);

Every err out-parameter may be null if you don’t need the error. Format names are case-insensitive. See Writer Options for each format’s options.

Example

#include "gridwell.h"
#include <stdio.h>
#include <string.h>

int main(void) {
    const char *json = "{ ... }";
    GridwellError *err = NULL;

    GridwellTable *table = gridwell_parse_ir(json, strlen(json), &err);
    if (!table) {
        fprintf(stderr, "Parse error: %s\n", gridwell_error_message(err));
        gridwell_free_error(err);
        return 1;
    }

    GridwellTextResult result = gridwell_render_text(table, "html", &err);
    if (result.text) {
        printf("%.*s\n", (int)result.len, result.text);
        gridwell_free_text_result(result);
    }

    gridwell_free_table(table);
    return 0;
}

Linking

Build the library with cargo build --release -p gridwell-ffi. That produces libgridwell_ffi.{so,dylib} and libgridwell_ffi.a in target/release/. Then:

cc -o myapp myapp.c -I crates/gridwell-ffi/include -L target/release -lgridwell_ffi

crates/gridwell-ffi/tests/c/smoke.c is a complete working example. The test suite compiles it as C99, as C++, and under AddressSanitizer.