c-capnproto#
Pure C runtime and capnpc-c for Cap’n Proto. Wire encode is byte-equivalent with
official capnp 1.0.2 when objects are allocated in schema order.
Sibling runtimes: capnp-fortran and capnp-janet.
Warning
Failed pointer hops are still CAPN_NULL; check capn_ok.
This is not C++ MessageReader throw-parity. See SECURITY.md.
Install (shortest path)#
$ git clone --recurse-submodules https://github.com/HaoZeke/c-capnproto.git
$ cd c-capnproto
$ meson setup build && meson compile -C build
$ meson test -C build
First message#
Schema is tests/addressbook.capnp (same shape as the C++ sample).
Generate accessors, then write and read a Person:
$ capnp compile -Icompiler -oc:build tests/addressbook.capnp
#include "capnp_c.h"
#include "addressbook.capnp.h"
static capn_text txt(const char *s) {
return (capn_text){.len = (int)strlen(s), .str = s, .seg = NULL};
}
uint8_t buf[4096];
struct capn c;
capn_init_malloc(&c);
struct Person p = {
.id = 17,
.name = txt("Firstname Lastname"),
.email = txt("username@domain.com"),
};
p.employment_which = Person_employment_school;
p.employment.school = txt("of life");
Person_ptr pp = new_Person(capn_root(&c).seg);
write_Person(&p, pp);
capn_set_root(&c, pp.p); /* required; otherwise the message is empty */
ssize_t sz = capn_write_mem(&c, buf, sizeof buf, 0);
capn_free(&c);
struct capn rc;
capn_init_mem(&rc, buf, sz, 0);
struct Person rp;
Person_ptr rp_ptr = {.p = capn_getp(capn_root(&rc), 0, 1)};
read_Person(&rp, rp_ptr);
/* rp.id == 17, rp.name.str == "Firstname Lastname" */
capn_free(&rc);
The full walk-through (phones list, union, packed, canonical) is the tutorial.
Documentation map#
Meson (recommended), CMake, autotools, optional kernel module.
AddressBook: generate, write, read, packed, canonicalize.
capnpc-c, capn_set_root, $C.fieldgetset, has_.
Schema-order encode, empty struct B=-1, packed 0xFF heuristic.
Official capnp CLI memcmp, fortran goldens, Janet peer.