Merge branch 'pull/16'

This commit is contained in:
David Lamparter 2017-04-05 22:44:10 +02:00
commit 7c819065e0
17 changed files with 801 additions and 99 deletions

2
.gitignore vendored
View file

@ -17,6 +17,8 @@ test-driver
*.log
*.trs
tests/*.out
*.o
*.a
*.so

View file

@ -17,8 +17,9 @@ pkgconfig_DATA = c-capnproto.pc
EXTRA_DIST += compiler/c.capnp
capnp_DATA = compiler/c.capnp
AM_CPPFLAGS = -I${srcdir}/lib
AM_CPPFLAGS = \
-I${srcdir}/compiler \
-I${srcdir}/lib
lib_LTLIBRARIES += libcapnp_c.la
libcapnp_c_la_LDFLAGS = -version-info 0:0:0
@ -42,25 +43,52 @@ noinst_HEADERS += \
lib/capnp_priv.h \
compiler/str.h \
compiler/schema.capnp.h \
compiler/c++.capnp.h \
compiler/test.capnp.h
compiler/c.capnp.h \
compiler/c++.capnp.h
# Don't try to generate any *.capnp files. Otherwise make wants to compile them
# from *.capnp.c and fails.
%.capnp: ;
# googletest
GTEST_LDADD = gtest/googletest/lib/libgtest.la
gtest/googletest/lib/libgtest.la:
make -C gtest/googletest lib/libgtest.la
GTEST_CPPFLAGS = -I${srcdir}/gtest/googletest/include
DIST_SUBDIRS = gtest/googletest
# Tests
check_PROGRAMS += \
capn-test
capn_test_SOURCES = \
tests/capn-test.cpp \
tests/capn-stream-test.cpp \
tests/example-test.cpp \
tests/addressbook.capnp.c \
compiler/test.capnp.c \
compiler/schema-test.cpp \
compiler/schema.capnp.c
noinst_HEADERS += \
compiler/test.capnp.h \
tests/addressbook.capnp.h
EXTRA_DIST += \
compiler/c.capnp \
compiler/c++.capnp \
compiler/schema.capnp \
compiler/test.capnp \
tests/addressbook.capnp
capn_test_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_CPPFLAGS)
capn_test_CXXFLAGS = -std=gnu++11 -pthread
capn_test_LDADD = libcapnp_c.la $(GTEST_LDADD)
capn_test_LDFLAGS = -pthread
TESTS = capn-test
CAPNP_SCHEMA_FILES := $(shell find . -type f -name \*.capnp)
CAPNP ?= capnp
.PHONY: capnp-compile
capnp-compile:
$(CAPNP) compile \
--output=./capnpc-c \
-Icompiler \
$(CAPNP_SCHEMA_FILES)

106
README.md
View file

@ -4,44 +4,19 @@ capnpc-c
This is a C plugin for [Cap'n Proto](http://kentonv.github.io/capnproto), an
efficient protocol for sharing data and capabilities.
This is only the plugin, to properly make use of it you need to download, build
and install capnpc and then build and install this project and then you can
utilize it as:
This is only the code generator plugin, to properly make use of it you
need to download, build and install capnpc and then build and install
this project and then you can utilize it as:
```sh
capnpc compiler/test.capnp -oc
```
[![Build Status](https://travis-ci.org/opensourcerouting/c-capnproto.svg?branch=master)](https://travis-ci.org/opensourcerouting/c-capnproto)
## status
## Building on Linux
This is a merge of 3 forks of [James McKaskill's great
work](https://github.com/jmckaskill/c-capnproto), which has been untouched for
a while:
- [liamstask's fork](https://github.com/liamstask/c-capnproto)
- [baruch's fork](https://github.com/baruch/c-capnproto)
- [kylemanna's fork](https://github.com/kylemanna/c-capnproto)
## usage
The `compiler` directory contains the C language plugin (`capnpc-c`) for use with the `capnp` tool: https://capnproto.org/capnp-tool.html.
`capnp` will by default search `$PATH` for `capnpc-c` - if it's on your PATH, you can generate code for your schema as follows:
$ capnp compile -o c myschema.capnp
Otherwise, you can specify the path to the c plugin:
$ capnp compile -o ./capnpc-c myschema.capnp
`capnp` generates a C struct that corresponds to each capn proto struct, along with read/write functions that convert to/from capn proto form.
TBD whether it will make sense in the future to provide accessor functions for struct members, rather than converting entire structs.
## building on linux
```
```sh
git clone https://github.com/opensourcerouting/c-capnproto
cd c-capnproto
git submodule update --init --recursive
@ -51,3 +26,70 @@ make
make check
```
## Usage
### Generating C code from a `.capnp` schema file
The `compiler` directory contains the C language plugin (`capnpc-c`) for use with the `capnp` tool: https://capnproto.org/capnp-tool.html.
`capnp` will by default search `$PATH` for `capnpc-c` - if it's on your PATH, you can generate code for your schema as follows:
```sh
capnp compile -o c myschema.capnp
```
Otherwise, you can specify the path to the c plugin:
```sh
capnp compile -o ./capnpc-c myschema.capnp
```
`capnp` generates a C struct that corresponds to each capn proto struct, along with read/write functions that convert to/from capn proto form.
If you want accessor functions for struct members, use attribute `fieldgetset` in your `.capnp` file as follows:
```capnp
using C = import "${c-capnproto}/compiler/c.capnp";
$C.fieldgetset;
struct MyStruct {}
```
### Example C code
See the unit tests in [`tests/example-test.cpp`](tests/example-test.cpp).
The example schema file is [`tests/addressbook.capnp`](tests/addressbook.capnp).
The tests are written in C++, but only use C features.
You need to compile these runtime library files and link them into your own project's binaries:
* [`lib/capn.c`](lib/capn.c)
* [`lib/capn-malloc.c`](lib/capn-malloc.c)
* [`lib/capn-stream.c`](lib/capn-stream.c)
Your include path must contain the runtime library directory
[`lib`](lib). Header file [`lib/capnp_c.h`](lib/capnp_c.h) contains
the public interfaces of the library.
Using make-based builds, make may try to compile `${x}.capnp` from
`${x}.capnp.c` using its built-in rule for compiling `${y}` from
`${y}.c`. You can either disable make's built-in compile rules or just
this specific case with the no-op rule: `%.capnp: ;`.
For further reference, please see the other unit tests in [`tests`](tests), and header file [`lib/capnp_c.h`](lib/capnp_c.h).
The project [`quagga-capnproto`](https://github.com/opensourcerouting/quagga-capnproto) uses `c-capnproto` and contains some good examples, as found with [this github repository search](https://github.com/opensourcerouting/quagga-capnproto/search?utf8=%E2%9C%93&q=capn&type=):
* Serialization in function [`bgp_notify_send()`](https://github.com/opensourcerouting/quagga-capnproto/blob/27061648f3418fac0d217b16a46add534343e841/bgpd/bgp_zmq.c#L81-L96) in file `quagga-capnproto/bgpd/bgp_zmq.c`
* Deserialization in function [`qzc_callback()`](https://github.com/opensourcerouting/quagga-capnproto/blob/27061648f3418fac0d217b16a46add534343e841/lib/qzc.c#L249-L257) in file `quagga-capnproto/lib/qzc.c`
## Status
This is a merge of 3 forks of [James McKaskill's great
work](https://github.com/jmckaskill/c-capnproto), which has been untouched for
a while:
- [liamstask's fork](https://github.com/liamstask/c-capnproto)
- [baruch's fork](https://github.com/baruch/c-capnproto)
- [kylemanna's fork](https://github.com/kylemanna/c-capnproto)

View file

@ -29,6 +29,10 @@ annotation nameinfix @0x85a8d86d736ba637 (file): Text;
# to a loop. $nameinfix (recommended parameter: "-gen") inserts its parameter
# before the ".c", so the filename becomes "foo-gen.c"
#
# Alternatively, add this Makefile rule to disable compiling "foo.capnp.c" -> "foo.capnp":
# %.capnp: ;
#
#
# ("foo" is really "foo.capnp", so it's foo.capnp-gen.c)
annotation fieldgetset @0xf72bc690355d66de (file): Void;

2
compiler/c.capnp.c Normal file
View file

@ -0,0 +1,2 @@
#include "c.capnp.h"
/* AUTO GENERATED - DO NOT EDIT */

27
compiler/c.capnp.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef CAPN_C0183DD65FFEF0F3
#define CAPN_C0183DD65FFEF0F3
/* AUTO GENERATED - DO NOT EDIT */
#include <capnp_c.h>
#if CAPN_VERSION != 1
#error "version mismatch between capnp_c.h and generated code"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -8,6 +8,7 @@
#include "schema.capnp.h"
#include "str.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
@ -261,6 +262,7 @@ static void decode_value(struct value* v, Type_ptr type, Value_ptr value, const
v->ptrval = p;
bool symbol_provided = symbol;
if (!symbol) {
static struct str buf = STR_INIT;
v->intval = ++g_valc;
@ -268,7 +270,7 @@ static void decode_value(struct value* v, Type_ptr type, Value_ptr value, const
}
str_addf(&SRC, "%scapn_text %s = {%d,(char*)&capn_buf[%d],(struct capn_segment*)&capn_seg};\n",
symbol ? "" : "static ",
symbol_provided ? "" : "static ",
symbol,
p.len-1,
(int) (p.data-p.seg->data-8));
@ -291,13 +293,14 @@ static void decode_value(struct value* v, Type_ptr type, Value_ptr value, const
v->ptrval = p;
bool symbol_provided = symbol;
if (!symbol) {
static struct str buf = STR_INIT;
v->intval = ++g_valc;
symbol = strf(&buf, "capn_val%d", (int) v->intval);
}
str_addf(&SRC, "%s%s %s = {", symbol ? "" : "static ", v->tname, symbol);
str_addf(&SRC, "%s%s %s = {", symbol_provided ? "" : "static ", v->tname, symbol);
if (strcmp(v->tname, "capn_ptr"))
str_addf(&SRC, "{");
@ -1290,7 +1293,11 @@ int main() {
for (j = 0; j < capn_len(file_req.imports); j++) {
struct CodeGeneratorRequest_RequestedFile_Import im;
get_CodeGeneratorRequest_RequestedFile_Import(&im, file_req.imports, j);
str_addf(&HDR, "#include \"%s%s.h\"\n", im.name.str, nameinfix);
// Ignore leading slashes when generating C file #include's.
// This signifies an absolute import in a library directory.
const char *base_path = im.name.str[0] == '/' ? &im.name.str[1] : im.name.str;
str_addf(&HDR, "#include \"%s%s.h\"\n", base_path, nameinfix);
}
str_addf(&HDR, "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n");

View file

@ -19,11 +19,14 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
using C = import "c.capnp";
using Cxx = import "c++.capnp";
@0xa93fc509624c72d9;
$Cxx.namespace("capnp::schema");
$C.fieldgetset;
using Id = UInt64;
# The globally-unique ID of a file, type, or annotation.

View file

@ -1,6 +1,6 @@
#include "schema.capnp.h"
/* AUTO GENERATED - DO NOT EDIT */
static const capn_text capn_val0 = {0,""};
static const capn_text capn_val0 = {0,"",0};
uint16_t Field_noDiscriminant = 65535;
Node_ptr new_Node(struct capn_segment *s) {

View file

@ -8,6 +8,7 @@
#endif
#include "c++.capnp.h"
#include "c.capnp.h"
#ifdef __cplusplus
extern "C" {

View file

@ -21,8 +21,11 @@
@0xd508eebdc2dc42b8;
using C = import "c.capnp";
using Cxx = import "c++.capnp";
$C.fieldgetset;
# Use a namespace likely to cause trouble if the generated code doesn't use fully-qualified
# names for stuff in the capnproto namespace.
$Cxx.namespace("capnproto_test::capnp::test");

View file

@ -1,19 +1,43 @@
#include "test.capnp.h"
/* AUTO GENERATED - DO NOT EDIT */
static const capn_text capn_val0 = {0,""};
static const capn_text capn_val0 = {0,"",0};
static const capn_ptr capn_null = {CAPN_NULL};
static const uint8_t capn_buf[72] = {
static const uint8_t capn_buf[264] = {
102,111,111,0,0,0,0,0,
98,97,114,0,0,0,0,0,
9,0,0,0,0,0,0,0,
111,145,0,0,0,0,0,0,
103,43,153,212,0,0,0,0,
199,107,159,6,57,148,96,249,
199,113,196,43,171,117,107,15,
57,142,59,212,84,138,148,240,
111,222,0,0,0,0,0,0
1,244,128,13,14,16,76,251,
78,115,232,56,166,51,0,0,
90,0,210,4,20,136,98,3,
210,10,111,18,33,25,204,4,
95,112,9,175,2,0,0,0,
0,0,0,0,0,144,117,64,
77,0,0,0,34,0,0,0,
77,0,0,0,26,0,0,0,
2,0,0,0,1,0,0,0,
73,0,0,0,24,0,0,0,
69,0,0,0,41,0,0,0,
69,0,0,0,34,0,0,0,
69,0,0,0,35,0,0,0,
194,1,0,0,1,0,0,0,
218,1,0,0,1,0,0,0,
2,2,0,0,1,0,0,0,
18,2,0,0,1,0,0,0,
34,2,0,0,1,0,0,0,
58,2,0,0,1,0,0,0,
98,2,0,0,1,0,0,0,
130,2,0,0,1,0,0,0,
186,2,0,0,1,0,0,0,
242,2,0,0,1,0,0,0,
42,3,0,0,1,0,0,0,
218,5,0,0,1,0,0,0,
0,0,0,0,0,0,0,0,
98,97,122,0,0,0,0,0,
113,117,120,0,0,0,0,0,
26,0,0,0,0,0,0,0,
12,222,128,127,0,0,0,0,
210,4,210,233,0,128,255,127
};
static const struct capn_segment capn_seg = {{0},0,0,0,(char*)&capn_buf[0],72,72};
static const struct capn_segment capn_seg = {{0},0,0,0,(char*)&capn_buf[0],264,264,0};
union capn_conv_f32 TestWholeFloatDefault_constant = {0x43e40000u};
union capn_conv_f32 TestWholeFloatDefault_bigConstant = {0x7249f2cau};
unsigned TestConstants_boolConst = 1;
@ -29,29 +53,29 @@ union capn_conv_f32 TestConstants_float32Const = {0x449a5000u};
union capn_conv_f64 TestConstants_float64Const = {((uint64_t) 0xc9b58b82u << 32) | 0xc0e0bb00u};
capn_text TestConstants_textConst = {3,(char*)&capn_buf[0],(struct capn_segment*)&capn_seg};
capn_data TestConstants_dataConst = {{2,0,0,0,1,0,3,(char*)&capn_buf[8],(struct capn_segment*)&capn_seg}};
TestAllTypes_ptr TestConstants_structConst = {{1,1,0,0,48,20,0,(char*)&capn_buf[0],(struct capn_segment*)&capn_seg}};
TestAllTypes_ptr TestConstants_structConst = {{1,0,0,0,48,20,0,(char*)&capn_buf[16],(struct capn_segment*)&capn_seg}};
enum TestEnum TestConstants_enumConst = (enum TestEnum) 5u;
capn_ptr TestConstants_voidListConst = {2,0,0,0,0,0,6,(char*)&capn_buf[16],(struct capn_segment*)&capn_seg};
capn_list1 TestConstants_boolListConst = {{4,0,0,0,1,0,4,(char*)&capn_buf[16],(struct capn_segment*)&capn_seg}};
capn_list8 TestConstants_int8ListConst = {{2,0,0,0,1,0,2,(char*)&capn_buf[24],(struct capn_segment*)&capn_seg}};
capn_list16 TestConstants_int16ListConst = {{2,0,0,0,2,0,2,(char*)&capn_buf[32],(struct capn_segment*)&capn_seg}};
capn_list32 TestConstants_int32ListConst = {{2,0,0,0,4,0,2,(char*)&capn_buf[40],(struct capn_segment*)&capn_seg}};
capn_list64 TestConstants_int64ListConst = {{2,0,0,0,8,0,2,(char*)&capn_buf[48],(struct capn_segment*)&capn_seg}};
capn_list8 TestConstants_uint8ListConst = {{2,0,0,0,1,0,2,(char*)&capn_buf[64],(struct capn_segment*)&capn_seg}};
capn_list16 TestConstants_uint16ListConst = {{2,1,0,0,2,0,2,(char*)&capn_buf[1664],(struct capn_segment*)&capn_seg}};
capn_list32 TestConstants_uint32ListConst = {{2,1,0,0,4,0,1,(char*)&capn_buf[1680],(struct capn_segment*)&capn_seg}};
capn_list64 TestConstants_uint64ListConst = {{2,1,0,0,8,0,1,(char*)&capn_buf[1696],(struct capn_segment*)&capn_seg}};
capn_list32 TestConstants_float32ListConst = {{2,1,0,0,4,0,4,(char*)&capn_buf[1712],(struct capn_segment*)&capn_seg}};
capn_list64 TestConstants_float64ListConst = {{2,1,0,0,8,0,4,(char*)&capn_buf[1736],(struct capn_segment*)&capn_seg}};
capn_ptr TestConstants_textListConst = {3,1,0,0,0,0,3,(char*)&capn_buf[1776],(struct capn_segment*)&capn_seg};
capn_ptr TestConstants_dataListConst = {3,1,0,0,0,0,3,(char*)&capn_buf[1832],(struct capn_segment*)&capn_seg};
TestAllTypes_list TestConstants_structListConst = {{2,1,0,1,48,20,3,(char*)&capn_buf[1904],(struct capn_segment*)&capn_seg}};
capn_list16 TestConstants_enumListConst = {{2,1,0,0,2,0,2,(char*)&capn_buf[2584],(struct capn_segment*)&capn_seg}};
capn_ptr TestConstants_voidListConst = {2,0,0,0,0,0,6,(char*)&capn_buf[264],(struct capn_segment*)&capn_seg};
capn_list1 TestConstants_boolListConst = {{4,1,0,0,1,0,4,(char*)&capn_buf[1512],(struct capn_segment*)&capn_seg}};
capn_list8 TestConstants_int8ListConst = {{2,1,0,0,1,0,2,(char*)&capn_buf[1528],(struct capn_segment*)&capn_seg}};
capn_list16 TestConstants_int16ListConst = {{2,1,0,0,2,0,2,(char*)&capn_buf[1544],(struct capn_segment*)&capn_seg}};
capn_list32 TestConstants_int32ListConst = {{2,1,0,0,4,0,2,(char*)&capn_buf[1560],(struct capn_segment*)&capn_seg}};
capn_list64 TestConstants_int64ListConst = {{2,1,0,0,8,0,2,(char*)&capn_buf[1576],(struct capn_segment*)&capn_seg}};
capn_list8 TestConstants_uint8ListConst = {{2,1,0,0,1,0,2,(char*)&capn_buf[1600],(struct capn_segment*)&capn_seg}};
capn_list16 TestConstants_uint16ListConst = {{2,1,0,0,2,0,2,(char*)&capn_buf[1616],(struct capn_segment*)&capn_seg}};
capn_list32 TestConstants_uint32ListConst = {{2,1,0,0,4,0,1,(char*)&capn_buf[1632],(struct capn_segment*)&capn_seg}};
capn_list64 TestConstants_uint64ListConst = {{2,1,0,0,8,0,1,(char*)&capn_buf[1648],(struct capn_segment*)&capn_seg}};
capn_list32 TestConstants_float32ListConst = {{2,1,0,0,4,0,4,(char*)&capn_buf[1664],(struct capn_segment*)&capn_seg}};
capn_list64 TestConstants_float64ListConst = {{2,1,0,0,8,0,4,(char*)&capn_buf[1688],(struct capn_segment*)&capn_seg}};
capn_ptr TestConstants_textListConst = {3,1,0,0,0,0,3,(char*)&capn_buf[1728],(struct capn_segment*)&capn_seg};
capn_ptr TestConstants_dataListConst = {3,1,0,0,0,0,3,(char*)&capn_buf[1784],(struct capn_segment*)&capn_seg};
TestAllTypes_list TestConstants_structListConst = {{2,1,0,1,48,20,3,(char*)&capn_buf[1856],(struct capn_segment*)&capn_seg}};
capn_list16 TestConstants_enumListConst = {{2,1,0,0,2,0,2,(char*)&capn_buf[2536],(struct capn_segment*)&capn_seg}};
uint32_t globalInt = 12345u;
capn_text globalText = {6,(char*)&capn_buf[2600],(struct capn_segment*)&capn_seg};
TestAllTypes_ptr globalStruct = {{1,1,0,0,48,20,0,(char*)&capn_buf[2616],(struct capn_segment*)&capn_seg}};
TestPrintInlineStructs_ptr globalPrintableStruct = {{1,1,0,0,0,2,0,(char*)&capn_buf[2832],(struct capn_segment*)&capn_seg}};
TestAllTypes_ptr derivedConstant = {{1,1,0,0,48,20,0,(char*)&capn_buf[2864],(struct capn_segment*)&capn_seg}};
capn_text globalText = {6,(char*)&capn_buf[2552],(struct capn_segment*)&capn_seg};
TestAllTypes_ptr globalStruct = {{1,1,0,0,48,20,0,(char*)&capn_buf[2568],(struct capn_segment*)&capn_seg}};
TestPrintInlineStructs_ptr globalPrintableStruct = {{1,1,0,0,0,2,0,(char*)&capn_buf[2784],(struct capn_segment*)&capn_seg}};
TestAllTypes_ptr derivedConstant = {{1,1,0,0,48,20,0,(char*)&capn_buf[2816],(struct capn_segment*)&capn_seg}};
TestAllTypes_ptr new_TestAllTypes(struct capn_segment *s) {
TestAllTypes_ptr p;
@ -527,25 +551,25 @@ void TestAllTypes_set_interfaceList(TestAllTypes_ptr p, capn_ptr interfaceList)
{
capn_setp(p.p, 19, interfaceList);
}
capn_text capn_val1 = {3,(char*)&capn_buf[1464],(struct capn_segment*)&capn_seg};
capn_data capn_val2 = {{2,1,0,0,1,0,3,(char*)&capn_buf[1480],(struct capn_segment*)&capn_seg}};
TestAllTypes_ptr capn_val3 = {{1,1,0,0,48,20,0,(char*)&capn_buf[1496],(struct capn_segment*)&capn_seg}};
capn_ptr capn_val4 = {2,0,0,0,0,0,6,(char*)&capn_buf[72],(struct capn_segment*)&capn_seg};
capn_list1 capn_val5 = {{4,1,0,0,1,0,4,(char*)&capn_buf[3160],(struct capn_segment*)&capn_seg}};
capn_list8 capn_val6 = {{2,1,0,0,1,0,2,(char*)&capn_buf[3176],(struct capn_segment*)&capn_seg}};
capn_list16 capn_val7 = {{2,1,0,0,2,0,2,(char*)&capn_buf[3192],(struct capn_segment*)&capn_seg}};
capn_list32 capn_val8 = {{2,1,0,0,4,0,2,(char*)&capn_buf[3208],(struct capn_segment*)&capn_seg}};
capn_list64 capn_val9 = {{2,1,0,0,8,0,2,(char*)&capn_buf[3224],(struct capn_segment*)&capn_seg}};
capn_list8 capn_val10 = {{2,1,0,0,1,0,2,(char*)&capn_buf[3248],(struct capn_segment*)&capn_seg}};
capn_list16 capn_val11 = {{2,1,0,0,2,0,2,(char*)&capn_buf[3264],(struct capn_segment*)&capn_seg}};
capn_list32 capn_val12 = {{2,1,0,0,4,0,1,(char*)&capn_buf[3280],(struct capn_segment*)&capn_seg}};
capn_list64 capn_val13 = {{2,1,0,0,8,0,1,(char*)&capn_buf[3296],(struct capn_segment*)&capn_seg}};
capn_list32 capn_val14 = {{2,1,0,0,4,0,4,(char*)&capn_buf[3312],(struct capn_segment*)&capn_seg}};
capn_list64 capn_val15 = {{2,1,0,0,8,0,4,(char*)&capn_buf[3336],(struct capn_segment*)&capn_seg}};
capn_ptr capn_val16 = {3,1,0,0,0,0,3,(char*)&capn_buf[3376],(struct capn_segment*)&capn_seg};
capn_ptr capn_val17 = {3,1,0,0,0,0,3,(char*)&capn_buf[3432],(struct capn_segment*)&capn_seg};
TestAllTypes_list capn_val18 = {{2,1,0,1,48,20,3,(char*)&capn_buf[8],(struct capn_segment*)&capn_seg}};
capn_list16 capn_val19 = {{2,1,0,0,2,0,2,(char*)&capn_buf[3496],(struct capn_segment*)&capn_seg}};
static capn_text capn_val1 = {3,(char*)&capn_buf[1408],(struct capn_segment*)&capn_seg};
static capn_data capn_val2 = {{2,1,0,0,1,0,3,(char*)&capn_buf[1424],(struct capn_segment*)&capn_seg}};
static TestAllTypes_ptr capn_val3 = {{1,1,0,0,48,20,0,(char*)&capn_buf[1440],(struct capn_segment*)&capn_seg}};
static capn_ptr capn_val4 = {2,0,0,0,0,0,6,(char*)&capn_buf[264],(struct capn_segment*)&capn_seg};
static capn_list1 capn_val5 = {{4,1,0,0,1,0,4,(char*)&capn_buf[3104],(struct capn_segment*)&capn_seg}};
static capn_list8 capn_val6 = {{2,1,0,0,1,0,2,(char*)&capn_buf[3120],(struct capn_segment*)&capn_seg}};
static capn_list16 capn_val7 = {{2,1,0,0,2,0,2,(char*)&capn_buf[3136],(struct capn_segment*)&capn_seg}};
static capn_list32 capn_val8 = {{2,1,0,0,4,0,2,(char*)&capn_buf[3152],(struct capn_segment*)&capn_seg}};
static capn_list64 capn_val9 = {{2,1,0,0,8,0,2,(char*)&capn_buf[3168],(struct capn_segment*)&capn_seg}};
static capn_list8 capn_val10 = {{2,1,0,0,1,0,2,(char*)&capn_buf[3192],(struct capn_segment*)&capn_seg}};
static capn_list16 capn_val11 = {{2,1,0,0,2,0,2,(char*)&capn_buf[3208],(struct capn_segment*)&capn_seg}};
static capn_list32 capn_val12 = {{2,1,0,0,4,0,1,(char*)&capn_buf[3224],(struct capn_segment*)&capn_seg}};
static capn_list64 capn_val13 = {{2,1,0,0,8,0,1,(char*)&capn_buf[3240],(struct capn_segment*)&capn_seg}};
static capn_list32 capn_val14 = {{2,1,0,0,4,0,4,(char*)&capn_buf[3256],(struct capn_segment*)&capn_seg}};
static capn_list64 capn_val15 = {{2,1,0,0,8,0,4,(char*)&capn_buf[3280],(struct capn_segment*)&capn_seg}};
static capn_ptr capn_val16 = {3,1,0,0,0,0,3,(char*)&capn_buf[3320],(struct capn_segment*)&capn_seg};
static capn_ptr capn_val17 = {3,1,0,0,0,0,3,(char*)&capn_buf[3376],(struct capn_segment*)&capn_seg};
static TestAllTypes_list capn_val18 = {{2,1,0,1,48,20,3,(char*)&capn_buf[8],(struct capn_segment*)&capn_seg}};
static capn_list16 capn_val19 = {{2,1,0,0,2,0,2,(char*)&capn_buf[3440],(struct capn_segment*)&capn_seg}};
TestDefaults_ptr new_TestDefaults(struct capn_segment *s) {
TestDefaults_ptr p;
@ -1976,10 +2000,10 @@ void set_TestInterleavedGroups(const struct TestInterleavedGroups *s, TestInterl
p.p = capn_getp(l.p, i, 0);
write_TestInterleavedGroups(s, p);
}
TestUnion_ptr capn_val20 = {{1,1,0,0,64,2,0,(char*)&capn_buf[3512],(struct capn_segment*)&capn_seg}};
TestUnion_ptr capn_val21 = {{1,1,0,0,64,2,0,(char*)&capn_buf[3600],(struct capn_segment*)&capn_seg}};
TestUnnamedUnion_ptr capn_val22 = {{1,1,0,0,16,2,0,(char*)&capn_buf[3696],(struct capn_segment*)&capn_seg}};
TestUnnamedUnion_ptr capn_val23 = {{1,1,0,0,16,2,0,(char*)&capn_buf[3736],(struct capn_segment*)&capn_seg}};
static TestUnion_ptr capn_val20 = {{1,1,0,0,64,2,0,(char*)&capn_buf[3456],(struct capn_segment*)&capn_seg}};
static TestUnion_ptr capn_val21 = {{1,1,0,0,64,2,0,(char*)&capn_buf[3544],(struct capn_segment*)&capn_seg}};
static TestUnnamedUnion_ptr capn_val22 = {{1,1,0,0,16,2,0,(char*)&capn_buf[3640],(struct capn_segment*)&capn_seg}};
static TestUnnamedUnion_ptr capn_val23 = {{1,1,0,0,16,2,0,(char*)&capn_buf[3680],(struct capn_segment*)&capn_seg}};
TestUnionDefaults_ptr new_TestUnionDefaults(struct capn_segment *s) {
TestUnionDefaults_ptr p;
@ -3146,7 +3170,7 @@ void TestFieldZeroIsBit_set_thirdField(TestFieldZeroIsBit_ptr p, uint8_t thirdFi
{
capn_write8(p.p, 1, thirdField ^ 123u);
}
TestLists_ptr capn_val24 = {{1,1,0,0,0,10,0,(char*)&capn_buf[3792],(struct capn_segment*)&capn_seg}};
static TestLists_ptr capn_val24 = {{1,1,0,0,0,10,0,(char*)&capn_buf[3736],(struct capn_segment*)&capn_seg}};
TestListDefaults_ptr new_TestListDefaults(struct capn_segment *s) {
TestListDefaults_ptr p;
@ -3388,7 +3412,7 @@ void TestOldVersion_set_old3(TestOldVersion_ptr p, TestOldVersion_ptr old3)
{
capn_setp(p.p, 1, old3.p);
}
capn_text capn_val25 = {3,(char*)&capn_buf[1544],(struct capn_segment*)&capn_seg};
static capn_text capn_val25 = {3,(char*)&capn_buf[1480],(struct capn_segment*)&capn_seg};
TestNewVersion_ptr new_TestNewVersion(struct capn_segment *s) {
TestNewVersion_ptr p;

View file

@ -8,6 +8,7 @@
#endif
#include "c++.capnp.h"
#include "c.capnp.h"
#ifdef __cplusplus
extern "C" {

59
tests/addressbook.capnp Normal file
View file

@ -0,0 +1,59 @@
# Based on the addressbook.capnp example in the capnproto C++ project:
# https://github.com/sandstorm-io/capnproto/blob/6816634a08b08bc8f52b4ee809afb58389f19655/c%2B%2B/samples/addressbook.capnp
#
# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
# Licensed under the MIT License:
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
@0x9eb32e19f86ee174;
using C = import "/c.capnp";
$C.fieldgetset;
struct Person {
id @0 :UInt32;
name @1 :Text;
email @2 :Text;
phones @3 :List(PhoneNumber);
struct PhoneNumber {
number @0 :Text;
type @1 :Type;
enum Type {
mobile @0;
home @1;
work @2;
}
}
employment :union {
unemployed @4 :Void;
employer @5 :Text;
school @6 :Text;
selfEmployed @7 :Void;
# We assume that a person is only one of these.
}
}
struct AddressBook {
people @0 :List(Person);
}

200
tests/addressbook.capnp.c Normal file
View file

@ -0,0 +1,200 @@
#include "addressbook.capnp.h"
/* AUTO GENERATED - DO NOT EDIT */
static const capn_text capn_val0 = {0,"",0};
Person_ptr new_Person(struct capn_segment *s) {
Person_ptr p;
p.p = capn_new_struct(s, 8, 4);
return p;
}
Person_list new_Person_list(struct capn_segment *s, int len) {
Person_list p;
p.p = capn_new_list(s, len, 8, 4);
return p;
}
void read_Person(struct Person *s, Person_ptr p) {
capn_resolve(&p.p);
s->id = capn_read32(p.p, 0);
s->name = capn_get_text(p.p, 0, capn_val0);
s->email = capn_get_text(p.p, 1, capn_val0);
s->phones.p = capn_getp(p.p, 2, 0);
s->employment_which = (enum Person_employment_which)(int) capn_read16(p.p, 4);
switch (s->employment_which) {
case Person_employment_employer:
case Person_employment_school:
s->employment.school = capn_get_text(p.p, 3, capn_val0);
break;
default:
break;
}
}
void write_Person(const struct Person *s, Person_ptr p) {
capn_resolve(&p.p);
capn_write32(p.p, 0, s->id);
capn_set_text(p.p, 0, s->name);
capn_set_text(p.p, 1, s->email);
capn_setp(p.p, 2, s->phones.p);
capn_write16(p.p, 4, s->employment_which);
switch (s->employment_which) {
case Person_employment_employer:
case Person_employment_school:
capn_set_text(p.p, 3, s->employment.school);
break;
default:
break;
}
}
void get_Person(struct Person *s, Person_list l, int i) {
Person_ptr p;
p.p = capn_getp(l.p, i, 0);
read_Person(s, p);
}
void set_Person(const struct Person *s, Person_list l, int i) {
Person_ptr p;
p.p = capn_getp(l.p, i, 0);
write_Person(s, p);
}
uint32_t Person_get_id(Person_ptr p)
{
uint32_t id;
id = capn_read32(p.p, 0);
return id;
}
capn_text Person_get_name(Person_ptr p)
{
capn_text name;
name = capn_get_text(p.p, 0, capn_val0);
return name;
}
capn_text Person_get_email(Person_ptr p)
{
capn_text email;
email = capn_get_text(p.p, 1, capn_val0);
return email;
}
Person_PhoneNumber_list Person_get_phones(Person_ptr p)
{
Person_PhoneNumber_list phones;
phones.p = capn_getp(p.p, 2, 0);
return phones;
}
void Person_set_id(Person_ptr p, uint32_t id)
{
capn_write32(p.p, 0, id);
}
void Person_set_name(Person_ptr p, capn_text name)
{
capn_set_text(p.p, 0, name);
}
void Person_set_email(Person_ptr p, capn_text email)
{
capn_set_text(p.p, 1, email);
}
void Person_set_phones(Person_ptr p, Person_PhoneNumber_list phones)
{
capn_setp(p.p, 2, phones.p);
}
Person_PhoneNumber_ptr new_Person_PhoneNumber(struct capn_segment *s) {
Person_PhoneNumber_ptr p;
p.p = capn_new_struct(s, 8, 1);
return p;
}
Person_PhoneNumber_list new_Person_PhoneNumber_list(struct capn_segment *s, int len) {
Person_PhoneNumber_list p;
p.p = capn_new_list(s, len, 8, 1);
return p;
}
void read_Person_PhoneNumber(struct Person_PhoneNumber *s, Person_PhoneNumber_ptr p) {
capn_resolve(&p.p);
s->number = capn_get_text(p.p, 0, capn_val0);
s->type = (enum Person_PhoneNumber_Type)(int) capn_read16(p.p, 0);
}
void write_Person_PhoneNumber(const struct Person_PhoneNumber *s, Person_PhoneNumber_ptr p) {
capn_resolve(&p.p);
capn_set_text(p.p, 0, s->number);
capn_write16(p.p, 0, (uint16_t) (s->type));
}
void get_Person_PhoneNumber(struct Person_PhoneNumber *s, Person_PhoneNumber_list l, int i) {
Person_PhoneNumber_ptr p;
p.p = capn_getp(l.p, i, 0);
read_Person_PhoneNumber(s, p);
}
void set_Person_PhoneNumber(const struct Person_PhoneNumber *s, Person_PhoneNumber_list l, int i) {
Person_PhoneNumber_ptr p;
p.p = capn_getp(l.p, i, 0);
write_Person_PhoneNumber(s, p);
}
capn_text Person_PhoneNumber_get_number(Person_PhoneNumber_ptr p)
{
capn_text number;
number = capn_get_text(p.p, 0, capn_val0);
return number;
}
enum Person_PhoneNumber_Type Person_PhoneNumber_get_type(Person_PhoneNumber_ptr p)
{
enum Person_PhoneNumber_Type type;
type = (enum Person_PhoneNumber_Type)(int) capn_read16(p.p, 0);
return type;
}
void Person_PhoneNumber_set_number(Person_PhoneNumber_ptr p, capn_text number)
{
capn_set_text(p.p, 0, number);
}
void Person_PhoneNumber_set_type(Person_PhoneNumber_ptr p, enum Person_PhoneNumber_Type type)
{
capn_write16(p.p, 0, (uint16_t) (type));
}
AddressBook_ptr new_AddressBook(struct capn_segment *s) {
AddressBook_ptr p;
p.p = capn_new_struct(s, 0, 1);
return p;
}
AddressBook_list new_AddressBook_list(struct capn_segment *s, int len) {
AddressBook_list p;
p.p = capn_new_list(s, len, 0, 1);
return p;
}
void read_AddressBook(struct AddressBook *s, AddressBook_ptr p) {
capn_resolve(&p.p);
s->people.p = capn_getp(p.p, 0, 0);
}
void write_AddressBook(const struct AddressBook *s, AddressBook_ptr p) {
capn_resolve(&p.p);
capn_setp(p.p, 0, s->people.p);
}
void get_AddressBook(struct AddressBook *s, AddressBook_list l, int i) {
AddressBook_ptr p;
p.p = capn_getp(l.p, i, 0);
read_AddressBook(s, p);
}
void set_AddressBook(const struct AddressBook *s, AddressBook_list l, int i) {
AddressBook_ptr p;
p.p = capn_getp(l.p, i, 0);
write_AddressBook(s, p);
}
Person_list AddressBook_get_people(AddressBook_ptr p)
{
Person_list people;
people.p = capn_getp(p.p, 0, 0);
return people;
}
void AddressBook_set_people(AddressBook_ptr p, Person_list people)
{
capn_setp(p.p, 0, people.p);
}

134
tests/addressbook.capnp.h Normal file
View file

@ -0,0 +1,134 @@
#ifndef CAPN_9EB32E19F86EE174
#define CAPN_9EB32E19F86EE174
/* AUTO GENERATED - DO NOT EDIT */
#include <capnp_c.h>
#if CAPN_VERSION != 1
#error "version mismatch between capnp_c.h and generated code"
#endif
#include "c.capnp.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Person;
struct Person_PhoneNumber;
struct AddressBook;
typedef struct {capn_ptr p;} Person_ptr;
typedef struct {capn_ptr p;} Person_PhoneNumber_ptr;
typedef struct {capn_ptr p;} AddressBook_ptr;
typedef struct {capn_ptr p;} Person_list;
typedef struct {capn_ptr p;} Person_PhoneNumber_list;
typedef struct {capn_ptr p;} AddressBook_list;
enum Person_PhoneNumber_Type {
Person_PhoneNumber_Type_mobile = 0,
Person_PhoneNumber_Type_home = 1,
Person_PhoneNumber_Type_work = 2
};
enum Person_employment_which {
Person_employment_unemployed = 0,
Person_employment_employer = 1,
Person_employment_school = 2,
Person_employment_selfEmployed = 3
};
struct Person {
uint32_t id;
capn_text name;
capn_text email;
Person_PhoneNumber_list phones;
enum Person_employment_which employment_which;
union {
capn_text employer;
capn_text school;
} employment;
};
static const size_t Person_word_count = 1;
static const size_t Person_pointer_count = 4;
static const size_t Person_struct_bytes_count = 40;
uint32_t Person_get_id(Person_ptr p);
capn_text Person_get_name(Person_ptr p);
capn_text Person_get_email(Person_ptr p);
Person_PhoneNumber_list Person_get_phones(Person_ptr p);
void Person_set_id(Person_ptr p, uint32_t id);
void Person_set_name(Person_ptr p, capn_text name);
void Person_set_email(Person_ptr p, capn_text email);
void Person_set_phones(Person_ptr p, Person_PhoneNumber_list phones);
struct Person_PhoneNumber {
capn_text number;
enum Person_PhoneNumber_Type type;
};
static const size_t Person_PhoneNumber_word_count = 1;
static const size_t Person_PhoneNumber_pointer_count = 1;
static const size_t Person_PhoneNumber_struct_bytes_count = 16;
capn_text Person_PhoneNumber_get_number(Person_PhoneNumber_ptr p);
enum Person_PhoneNumber_Type Person_PhoneNumber_get_type(Person_PhoneNumber_ptr p);
void Person_PhoneNumber_set_number(Person_PhoneNumber_ptr p, capn_text number);
void Person_PhoneNumber_set_type(Person_PhoneNumber_ptr p, enum Person_PhoneNumber_Type type);
struct AddressBook {
Person_list people;
};
static const size_t AddressBook_word_count = 0;
static const size_t AddressBook_pointer_count = 1;
static const size_t AddressBook_struct_bytes_count = 8;
Person_list AddressBook_get_people(AddressBook_ptr p);
void AddressBook_set_people(AddressBook_ptr p, Person_list people);
Person_ptr new_Person(struct capn_segment*);
Person_PhoneNumber_ptr new_Person_PhoneNumber(struct capn_segment*);
AddressBook_ptr new_AddressBook(struct capn_segment*);
Person_list new_Person_list(struct capn_segment*, int len);
Person_PhoneNumber_list new_Person_PhoneNumber_list(struct capn_segment*, int len);
AddressBook_list new_AddressBook_list(struct capn_segment*, int len);
void read_Person(struct Person*, Person_ptr);
void read_Person_PhoneNumber(struct Person_PhoneNumber*, Person_PhoneNumber_ptr);
void read_AddressBook(struct AddressBook*, AddressBook_ptr);
void write_Person(const struct Person*, Person_ptr);
void write_Person_PhoneNumber(const struct Person_PhoneNumber*, Person_PhoneNumber_ptr);
void write_AddressBook(const struct AddressBook*, AddressBook_ptr);
void get_Person(struct Person*, Person_list, int i);
void get_Person_PhoneNumber(struct Person_PhoneNumber*, Person_PhoneNumber_list, int i);
void get_AddressBook(struct AddressBook*, AddressBook_list, int i);
void set_Person(const struct Person*, Person_list, int i);
void set_Person_PhoneNumber(const struct Person_PhoneNumber*, Person_PhoneNumber_list, int i);
void set_AddressBook(const struct AddressBook*, AddressBook_list, int i);
#ifdef __cplusplus
}
#endif
#endif

165
tests/example-test.cpp Normal file
View file

@ -0,0 +1,165 @@
/* example-test.cpp
*
* Some simple examples using c-capnproto.
*
* Based on the addressbook.capnp example in the capnproto C++ project:
* https://github.com/sandstorm-io/capnproto/blob/6816634a08b08bc8f52b4ee809afb58389f19655/c%2B%2B/samples/addressbook.capnp
*
* Copyright (C) 2017 Alex Helfet
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
#include <gtest/gtest.h>
#include <cstdint>
#include "capnp_c.h"
#include "addressbook.capnp.h"
static capn_text chars_to_text(const char *chars) {
return (capn_text) {
.len = (int) strlen(chars),
.str = chars,
.seg = NULL,
};
}
// EXPECT_CAPN_TEXT_EQ arguments:
// const char * expected
// capn_text t
#define EXPECT_CAPN_TEXT_EQ(expected, t) \
do { \
EXPECT_EQ(strlen((expected)), (uint32_t) (t).len); \
EXPECT_STREQ((expected), (t).str); \
} while(0);
// Demonstrates serializing an object tree to a byte array, then deserializing it
// back into an object tree and asserting on the expected values therein.
//
// This example uses generated read_*, write_*, get_*, set_* functions
// to deserialize into structs.
TEST(Examples, RoundTripPerson) {
uint8_t buf[4096];
ssize_t sz = 0;
const char *name = "Firstname Lastname";
const char *email = "username@domain.com";
const char *school = "of life";
{
struct capn c;
capn_init_malloc(&c);
capn_ptr cr = capn_root(&c);
struct capn_segment *cs = cr.seg;
// Set initial object in `p`.
struct Person p = {
.id = 17,
.name = chars_to_text(name),
.email = chars_to_text(email),
};
p.employment_which = Person_employment_school;
p.employment.school = chars_to_text(school);
p.phones = new_Person_PhoneNumber_list(cs, 2);
struct Person_PhoneNumber pn0 = {
.number = chars_to_text("123"),
.type = Person_PhoneNumber_Type_work,
};
set_Person_PhoneNumber(&pn0, p.phones, 0);
struct Person_PhoneNumber pn1 = {
.number = chars_to_text("234"),
.type = Person_PhoneNumber_Type_home,
};
set_Person_PhoneNumber(&pn1, p.phones, 1);
Person_ptr pp = new_Person(cs);
write_Person(&p, pp);
int setp_ret = capn_setp(capn_root(&c), 0, pp.p);
ASSERT_EQ(0, setp_ret);
sz = capn_write_mem(&c, buf, sizeof(buf), 0 /* packed */);
capn_free(&c);
}
{
// Write serialized object to file system.
FILE *f = fopen("tests/example-test.cpp.Person.out", "wb");
ASSERT_NE(f, (void*)0);
fwrite(buf, 1 /* size */, sz /* count */, f);
int close_ret = fclose(f);
ASSERT_EQ(0, close_ret);
}
{
// Deserialize `buf[0..sz-1]` to `rp`.
struct capn rc;
int init_mem_ret = capn_init_mem(&rc, buf, sz, 0 /* packed */);
ASSERT_EQ(0, init_mem_ret);
Person_ptr rroot;
struct Person rp;
rroot.p = capn_getp(capn_root(&rc), 0 /* off */, 1 /* resolve */);
read_Person(&rp, rroot);
// Assert deserialized values in `rp`
EXPECT_EQ(rp.id, (uint32_t) 17);
EXPECT_CAPN_TEXT_EQ(name, rp.name);
EXPECT_CAPN_TEXT_EQ(email, rp.email);
EXPECT_EQ(rp.employment_which, Person_employment_school);
EXPECT_CAPN_TEXT_EQ(school, rp.employment.school);
EXPECT_EQ(2, capn_len(rp.phones));
struct Person_PhoneNumber rpn0;
get_Person_PhoneNumber(&rpn0, rp.phones, 0);
EXPECT_CAPN_TEXT_EQ("123", rpn0.number);
EXPECT_EQ(rpn0.type, Person_PhoneNumber_Type_work);
struct Person_PhoneNumber rpn1;
get_Person_PhoneNumber(&rpn1, rp.phones, 1);
EXPECT_CAPN_TEXT_EQ("234", rpn1.number);
EXPECT_EQ(rpn1.type, Person_PhoneNumber_Type_home);
capn_free(&rc);
}
}
// Demonstrate accessing serialized objects using accessor functions without
// first copying values into structs.
TEST(Examples, PersonWithAccessors) {
struct capn c;
capn_init_malloc(&c);
capn_ptr cr = capn_root(&c);
struct capn_segment *cs = cr.seg;
// Set fields with set_ accessors.
Person_ptr pp = new_Person(cs);
{
Person_set_id(pp, 17);
capn_text name = chars_to_text("Name");
EXPECT_CAPN_TEXT_EQ("Name", name);
Person_set_name(pp, name);
Person_PhoneNumber_list pnl = new_Person_PhoneNumber_list(cs, 1);
Person_set_phones(pp, pnl);
Person_PhoneNumber_ptr pn0;
pn0.p = capn_getp(pnl.p, 0 /* offset */, 0 /* resolve */);
Person_PhoneNumber_set_type(pn0, Person_PhoneNumber_Type_home);
}
// Assert field values returned by get_ accessors.
{
EXPECT_EQ(Person_get_id(pp), 17);
EXPECT_CAPN_TEXT_EQ("Name", Person_get_name(pp));
Person_PhoneNumber_list pnl = Person_get_phones(pp);
Person_PhoneNumber_ptr pn0;
pn0.p = capn_getp(pnl.p, 0 /* offset */, 0 /* resolve */);
EXPECT_EQ(Person_PhoneNumber_Type_home, Person_PhoneNumber_get_type(pn0));
}
capn_free(&c);
}