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 buildQuick 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
| Function | Description |
|---|---|
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
| Function | Type |
|---|---|
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 outputDo 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:
| Kind | Constant | Meaning |
|---|---|---|
| Unexpected EOF | TWILIC_ERR_UNEXPECTED_EOF | Truncated payload |
| Invalid kind | TWILIC_ERR_INVALID_KIND | Corrupt wire data |
| Invalid tag | TWILIC_ERR_INVALID_TAG | Unknown tag byte |
| Invalid data | TWILIC_ERR_INVALID_DATA | Semantic error |
| UTF-8 | TWILIC_ERR_UTF8 | Invalid string |
| Unknown reference | TWILIC_ERR_UNKNOWN_REFERENCE | Missing session base |
| Stateless retry | TWILIC_ERR_STATELESS_RETRY_REQUIRED | Request 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.shC++ 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.