Skip to content

C API Reference

The C library (twilic-c) exposes a C11 public API for Dynamic, Bound, and Batch encoding. Session-aware APIs are in progress; the implementation is algorithmically aligned with twilic-cpp.

Installation

Build from source with CMake:

bash
git clone https://github.com/twilic/twilic-c.git
cd twilic-c
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
sudo cmake --install build

Quick start

c
#include "twilic/twilic.h"

twilic_map_entry_t entries[] = {
twilic_entry("id", twilic_u64(1001)),
twilic_entry("name", twilic_string("alice")),
};
twilic_value_t value = twilic_map(entries, 2);

twilic_buffer_t encoded = {0};
twilic_error_t err = {0};

if (twilic_encode(&value, &encoded, &err) != 0) {
fprintf(stderr, "encode: %s\n", err.msg);
return 1;
}

twilic_value_t decoded = twilic_null();
twilic_decode(encoded.data, encoded.len, &decoded, &err);

twilic_value_free(&decoded);
twilic_value_free(&value);
twilic_buffer_free(&encoded);

Core functions

FunctionDescription
twilic_encode(value, out, err)Dynamic profile encode
twilic_decode(data, len, out, err)Dynamic profile decode
twilic_encode_with_schema(schema, value, out, err)Bound profile encode
twilic_encode_batch(values, count, out, err)Row batch encode

Value constructors

FunctionType
twilic_null()null
twilic_bool(bool)boolean
twilic_i64(int64_t)signed integer
twilic_u64(uint64_t)unsigned integer
twilic_f64(double)float
twilic_string(const char *)string (copied)
twilic_binary(data, len)binary (copied)
twilic_array(items, count)array
twilic_map(entries, count)map
twilic_entry(key, value)map entry helper

Memory management

All heap-allocated values and buffers must be freed explicitly:

c
twilic_value_free(&value);   // recursive — frees nested arrays/maps
twilic_buffer_free(&buffer); // encoded output

Do not free string/binary pointers inside a twilic_value_t directly — use twilic_value_free.

Schema (Bound profile)

c
twilic_schema_field_t fields[] = {
{ .number = 1, .name = "id", .logical_type = "u64", .required = true },
{ .number = 2, .name = "name", .logical_type = "string", .required = true },
};

twilic_schema_t schema = {
.schema_id = 1,
.name = "UserRecordV1",
.fields = fields,
.fields_len = 2,
};

twilic_encode_with_schema(&schema, &value, &encoded, &err);

Error handling

Functions return 0 on success, non-zero on failure. Inspect twilic_error_t:

KindConstantMeaning
Unexpected EOFTWILIC_ERR_UNEXPECTED_EOFTruncated payload
Invalid kindTWILIC_ERR_INVALID_KINDCorrupt wire data
Invalid tagTWILIC_ERR_INVALID_TAGUnknown tag byte
Invalid dataTWILIC_ERR_INVALID_DATASemantic error
UTF-8TWILIC_ERR_UTF8Invalid string
Unknown referenceTWILIC_ERR_UNKNOWN_REFERENCEMissing session base
Stateless retryTWILIC_ERR_STATELESS_RETRY_REQUIREDRequest full frame
c
if (twilic_decode(data, len, &out, &err) != 0) {
fprintf(stderr, "decode failed: %s (kind=%d)\n", err.msg, err.kind);
}

Batch encoding

c
twilic_value_t records[256];
// ... fill records ...

twilic_buffer_t batch = {0};
twilic_error_t err = {0};
twilic_encode_batch(records, 256, &batch, &err);

for (size_t i = 0; i < 256; i++) {
twilic_value_free(&records[i]);
}
twilic_buffer_free(&batch);

Interop

Cross-language fixtures are verified against Rust and Go:

bash
./scripts/check-interop.sh

C++ note

Internal sources currently compile as C++17 for parity with twilic-cpp while the mechanical C11 port proceeds. The public header twilic.h is pure C11 — C++ projects can link the same library. For idiomatic C++ APIs, see twilic-cpp.

Released under the CC-BY-4.0 License.