From 362173091d4fbf3fa52ccd43fab2751f19018d68 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Thu, 23 Mar 2017 06:53:33 +0000 Subject: [PATCH 01/13] compiler: If an explicit symbol wasn't provided, make generated capn_val%d variables static. --- compiler/capnpc-c.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/capnpc-c.c b/compiler/capnpc-c.c index 4258f0a..51c382d 100644 --- a/compiler/capnpc-c.c +++ b/compiler/capnpc-c.c @@ -8,6 +8,7 @@ #include "schema.capnp.h" #include "str.h" +#include #include #include #include @@ -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, "{"); From 29a1342d00b902ed989a814840a217984236f80f Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Thu, 23 Mar 2017 20:12:44 +0000 Subject: [PATCH 02/13] Example usage in unit test. --- .gitignore | 2 + Makefile.am | 2 + README.md | 103 +++++++++++++++++++++++++++-------------- tests/example-test.cpp | 72 ++++++++++++++++++++++++++++ tests/example.capnp | 10 ++++ tests/example.capnp.c | 66 ++++++++++++++++++++++++++ tests/example.capnp.h | 54 +++++++++++++++++++++ 7 files changed, 274 insertions(+), 35 deletions(-) create mode 100644 tests/example-test.cpp create mode 100644 tests/example.capnp create mode 100644 tests/example.capnp.c create mode 100644 tests/example.capnp.h diff --git a/.gitignore b/.gitignore index 76d9560..c3a9d9d 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ test-driver *.log *.trs +tests/*.out + *.o *.a *.so diff --git a/Makefile.am b/Makefile.am index 8622c90..d2ea63c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,6 +56,8 @@ check_PROGRAMS += \ capn_test_SOURCES = \ tests/capn-test.cpp \ tests/capn-stream-test.cpp \ + tests/example-test.cpp \ + tests/example.capnp.c \ compiler/test.capnp.c \ compiler/schema-test.cpp \ compiler/schema.capnp.c diff --git a/README.md b/README.md index a9d9fa8..eac0af5 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,78 @@ 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: - capnpc compiler/test.capnp -oc +```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 + +```sh +git clone https://github.com/opensourcerouting/c-capnproto +cd c-capnproto +git submodule update --init --recursive +autoreconf -f -i -s +./configure +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/example.capnp`](tests/example.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. + +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 @@ -21,33 +84,3 @@ 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 - -``` -git clone https://github.com/opensourcerouting/c-capnproto -cd c-capnproto -git submodule update --init --recursive -autoreconf -f -i -s -./configure -make -make check -``` - diff --git a/tests/example-test.cpp b/tests/example-test.cpp new file mode 100644 index 0000000..cfec3f7 --- /dev/null +++ b/tests/example-test.cpp @@ -0,0 +1,72 @@ +/* example-test.cpp + * + * Some simple examples using c-capnproto + * + * 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 +#include + +#include "capnp_c.h" +#include "example.capnp.h" + +TEST(Examples, RoundTrip) { + uint8_t buf[4096]; + ssize_t sz = 0; + + const char *s = "Hello."; + + { + // Set initial object in `g`. + const capn_text capn_val0 = { + .len = strlen(s), + .str = s, + .seg = NULL + }; + struct Greeting g = { + .text = capn_val0, + .timesToSay = 17, + }; + + // Serialize `g` to `buf[0..sz-1]`. + struct capn c; + capn_init_malloc(&c); + capn_ptr cr = capn_root(&c); + struct capn_segment *cs = cr.seg; + Greeting_ptr gp = new_Greeting(cs); + write_Greeting(&g, gp); + int setp_ret = capn_setp(capn_root(&c), 0, gp.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.Greeting.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 `rg`. + struct capn rc; + int init_mem_ret = capn_init_mem(&rc, buf, sz, 0 /* packed */); + ASSERT_EQ(0, init_mem_ret); + Greeting_ptr rroot; + struct Greeting rg; + rroot.p = capn_getp(capn_root(&rc), 0 /* off */, 1 /* resolve */); + read_Greeting(&rg, rroot); + + // Assert deserialized values in `rg` + EXPECT_EQ(rg.timesToSay, 17); + EXPECT_EQ(strlen(s), (uint32_t) rg.text.len); + EXPECT_EQ(0, strncmp(s, rg.text.str, strlen(s))); + } +} diff --git a/tests/example.capnp b/tests/example.capnp new file mode 100644 index 0000000..36ebda2 --- /dev/null +++ b/tests/example.capnp @@ -0,0 +1,10 @@ +@0xd120e9a4c43868ab; + +using C = import "../compiler/c.capnp"; + +$C.fieldgetset; + +struct Greeting { + text @0 :Text = "Default greeting: hello world!"; + timesToSay @1 :UInt32; +} diff --git a/tests/example.capnp.c b/tests/example.capnp.c new file mode 100644 index 0000000..0c4dfed --- /dev/null +++ b/tests/example.capnp.c @@ -0,0 +1,66 @@ +#include "example.capnp.h" +/* AUTO GENERATED - DO NOT EDIT */ +static const capn_text capn_val0 = {0,"",0}; +static const uint8_t capn_buf[32] = { + 68,101,102,97,117,108,116,32, + 103,114,101,101,116,105,110,103, + 58,32,104,101,108,108,111,32, + 119,111,114,108,100,33,0,0 +}; +static const struct capn_segment capn_seg = {{0},0,0,0,(char*)&capn_buf[0],32,32,0}; +static capn_text capn_val1 = {30,(char*)&capn_buf[0],(struct capn_segment*)&capn_seg}; + +Greeting_ptr new_Greeting(struct capn_segment *s) { + Greeting_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +Greeting_list new_Greeting_list(struct capn_segment *s, int len) { + Greeting_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_Greeting(struct Greeting *s, Greeting_ptr p) { + capn_resolve(&p.p); + s->text = capn_get_text(p.p, 0, capn_val1); + s->timesToSay = capn_read32(p.p, 0); +} +void write_Greeting(const struct Greeting *s, Greeting_ptr p) { + capn_resolve(&p.p); + capn_set_text(p.p, 0, (s->text.str != capn_val1.str) ? s->text : capn_val0); + capn_write32(p.p, 0, s->timesToSay); +} +void get_Greeting(struct Greeting *s, Greeting_list l, int i) { + Greeting_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Greeting(s, p); +} +void set_Greeting(const struct Greeting *s, Greeting_list l, int i) { + Greeting_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Greeting(s, p); +} + +capn_text Greeting_get_text(Greeting_ptr p) +{ + capn_text text; + text = capn_get_text(p.p, 0, capn_val1); + return text; +} + +uint32_t Greeting_get_timesToSay(Greeting_ptr p) +{ + uint32_t timesToSay; + timesToSay = capn_read32(p.p, 0); + return timesToSay; +} + +void Greeting_set_text(Greeting_ptr p, capn_text text) +{ + capn_set_text(p.p, 0, (text.str != capn_val1.str) ? text : capn_val0); +} + +void Greeting_set_timesToSay(Greeting_ptr p, uint32_t timesToSay) +{ + capn_write32(p.p, 0, timesToSay); +} diff --git a/tests/example.capnp.h b/tests/example.capnp.h new file mode 100644 index 0000000..9342d23 --- /dev/null +++ b/tests/example.capnp.h @@ -0,0 +1,54 @@ +#ifndef CAPN_D120E9A4C43868AB +#define CAPN_D120E9A4C43868AB +/* AUTO GENERATED - DO NOT EDIT */ +#include + +#if CAPN_VERSION != 1 +#error "version mismatch between capnp_c.h and generated code" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct Greeting; + +typedef struct {capn_ptr p;} Greeting_ptr; + +typedef struct {capn_ptr p;} Greeting_list; + +struct Greeting { + capn_text text; + uint32_t timesToSay; +}; + +static const size_t Greeting_word_count = 1; + +static const size_t Greeting_pointer_count = 1; + +static const size_t Greeting_struct_bytes_count = 16; + +capn_text Greeting_get_text(Greeting_ptr p); + +uint32_t Greeting_get_timesToSay(Greeting_ptr p); + +void Greeting_set_text(Greeting_ptr p, capn_text text); + +void Greeting_set_timesToSay(Greeting_ptr p, uint32_t timesToSay); + +Greeting_ptr new_Greeting(struct capn_segment*); + +Greeting_list new_Greeting_list(struct capn_segment*, int len); + +void read_Greeting(struct Greeting*, Greeting_ptr); + +void write_Greeting(const struct Greeting*, Greeting_ptr); + +void get_Greeting(struct Greeting*, Greeting_list, int i); + +void set_Greeting(const struct Greeting*, Greeting_list, int i); + +#ifdef __cplusplus +} +#endif +#endif From e32a85be7917040ddb02546bae5ba245a6a8cf0c Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Fri, 24 Mar 2017 02:32:21 +0000 Subject: [PATCH 03/13] Fix build errors in tests/example-test.cpp. --- tests/example-test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/example-test.cpp b/tests/example-test.cpp index cfec3f7..4c4f202 100644 --- a/tests/example-test.cpp +++ b/tests/example-test.cpp @@ -23,7 +23,7 @@ TEST(Examples, RoundTrip) { { // Set initial object in `g`. const capn_text capn_val0 = { - .len = strlen(s), + .len = (int) strlen(s), .str = s, .seg = NULL }; @@ -65,7 +65,7 @@ TEST(Examples, RoundTrip) { read_Greeting(&rg, rroot); // Assert deserialized values in `rg` - EXPECT_EQ(rg.timesToSay, 17); + EXPECT_EQ(rg.timesToSay, (uint32_t) 17); EXPECT_EQ(strlen(s), (uint32_t) rg.text.len); EXPECT_EQ(0, strncmp(s, rg.text.str, strlen(s))); } From 5a282f6c98039a278e1846a6bcdf9eb60cc52f23 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Fri, 24 Mar 2017 18:02:22 +0000 Subject: [PATCH 04/13] Add extra files to Makefile.am. --- Makefile.am | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index d2ea63c..be2151b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,8 +42,7 @@ 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 GTEST_LDADD = gtest/googletest/lib/libgtest.la gtest/googletest/lib/libgtest.la: @@ -51,6 +50,7 @@ gtest/googletest/lib/libgtest.la: GTEST_CPPFLAGS = -I${srcdir}/gtest/googletest/include DIST_SUBDIRS = gtest/googletest +# Tests check_PROGRAMS += \ capn-test capn_test_SOURCES = \ @@ -61,6 +61,11 @@ capn_test_SOURCES = \ compiler/test.capnp.c \ compiler/schema-test.cpp \ compiler/schema.capnp.c +noinst_HEADERS += \ + compiler/test.capnp.h \ + tests/example.capnp.h +EXTRA_DIST += \ + tests/example.capnp capn_test_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_CPPFLAGS) capn_test_CXXFLAGS = -std=gnu++11 -pthread capn_test_LDADD = libcapnp_c.la $(GTEST_LDADD) From 6b52d615a2cdc6626f52f3d88884db776201144d Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Sun, 26 Mar 2017 15:23:35 +0100 Subject: [PATCH 05/13] Add all .capnp files to `make dist` archive. --- Makefile.am | 9 +++++++++ README.md | 5 +++++ compiler/c.capnp | 4 ++++ 3 files changed, 18 insertions(+) diff --git a/Makefile.am b/Makefile.am index be2151b..45ac3ed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,6 +44,11 @@ noinst_HEADERS += \ compiler/schema.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 @@ -65,6 +70,10 @@ noinst_HEADERS += \ compiler/test.capnp.h \ tests/example.capnp.h EXTRA_DIST += \ + compiler/c.capnp \ + compiler/c++.capnp \ + compiler/schema.capnp \ + compiler/test.capnp \ tests/example.capnp capn_test_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_CPPFLAGS) capn_test_CXXFLAGS = -std=gnu++11 -pthread diff --git a/README.md b/README.md index eac0af5..d12cd5d 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,11 @@ You need to compile these runtime library files and link them into your own proj 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=): diff --git a/compiler/c.capnp b/compiler/c.capnp index 5de7e73..9a0a1d3 100644 --- a/compiler/c.capnp +++ b/compiler/c.capnp @@ -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; From a379aa89ac2344bea5aa50e123766ae977361f08 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Sun, 26 Mar 2017 18:43:57 +0100 Subject: [PATCH 06/13] Compiler generates absolute #include paths from .capnp imports with leading /'s. As specified in https://capnproto.org/language.html#imports and implemented in the C++ compiler output plugin. --- compiler/capnpc-c.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/capnpc-c.c b/compiler/capnpc-c.c index 51c382d..b9c81de 100644 --- a/compiler/capnpc-c.c +++ b/compiler/capnpc-c.c @@ -1293,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"); From 73b5d565de4b2a90b09fc19118ac88102dd7bd84 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Sun, 26 Mar 2017 18:45:14 +0100 Subject: [PATCH 07/13] Make task `capnp-compile` to compile from .capnp files in the project. --- Makefile.am | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Makefile.am b/Makefile.am index 45ac3ed..04abd48 100644 --- a/Makefile.am +++ b/Makefile.am @@ -80,3 +80,13 @@ 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) From 989acc3414779902ed1164140b0d00458c5277b3 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Sun, 26 Mar 2017 23:40:55 +0100 Subject: [PATCH 08/13] Most .capnp files use "/c.capnp".fieldgetset. Recompile from schema files. --- Makefile.am | 5 +- compiler/c.capnp.c | 2 + compiler/c.capnp.h | 27 ++++++++ compiler/schema.capnp | 3 + compiler/schema.capnp.c | 2 +- compiler/schema.capnp.h | 1 + compiler/test.capnp | 3 + compiler/test.capnp.c | 136 +++++++++++++++++++++++----------------- compiler/test.capnp.h | 1 + tests/example.capnp | 2 +- tests/example.capnp.h | 2 + 11 files changed, 124 insertions(+), 60 deletions(-) create mode 100644 compiler/c.capnp.c create mode 100644 compiler/c.capnp.h diff --git a/Makefile.am b/Makefile.am index 04abd48..edf8d95 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/compiler/c.capnp.c b/compiler/c.capnp.c new file mode 100644 index 0000000..f940824 --- /dev/null +++ b/compiler/c.capnp.c @@ -0,0 +1,2 @@ +#include "c.capnp.h" +/* AUTO GENERATED - DO NOT EDIT */ diff --git a/compiler/c.capnp.h b/compiler/c.capnp.h new file mode 100644 index 0000000..07f769e --- /dev/null +++ b/compiler/c.capnp.h @@ -0,0 +1,27 @@ +#ifndef CAPN_C0183DD65FFEF0F3 +#define CAPN_C0183DD65FFEF0F3 +/* AUTO GENERATED - DO NOT EDIT */ +#include + +#if CAPN_VERSION != 1 +#error "version mismatch between capnp_c.h and generated code" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + + + + + + + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/compiler/schema.capnp b/compiler/schema.capnp index 1e7c615..169f775 100644 --- a/compiler/schema.capnp +++ b/compiler/schema.capnp @@ -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. diff --git a/compiler/schema.capnp.c b/compiler/schema.capnp.c index d362e52..2182cf9 100644 --- a/compiler/schema.capnp.c +++ b/compiler/schema.capnp.c @@ -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) { diff --git a/compiler/schema.capnp.h b/compiler/schema.capnp.h index 513b435..f5358ea 100644 --- a/compiler/schema.capnp.h +++ b/compiler/schema.capnp.h @@ -8,6 +8,7 @@ #endif #include "c++.capnp.h" +#include "c.capnp.h" #ifdef __cplusplus extern "C" { diff --git a/compiler/test.capnp b/compiler/test.capnp index 9c65721..fbee1f2 100644 --- a/compiler/test.capnp +++ b/compiler/test.capnp @@ -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"); diff --git a/compiler/test.capnp.c b/compiler/test.capnp.c index fa5cc7d..46dce92 100644 --- a/compiler/test.capnp.c +++ b/compiler/test.capnp.c @@ -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; diff --git a/compiler/test.capnp.h b/compiler/test.capnp.h index 7406a69..28a6bd1 100644 --- a/compiler/test.capnp.h +++ b/compiler/test.capnp.h @@ -8,6 +8,7 @@ #endif #include "c++.capnp.h" +#include "c.capnp.h" #ifdef __cplusplus extern "C" { diff --git a/tests/example.capnp b/tests/example.capnp index 36ebda2..cbf7c45 100644 --- a/tests/example.capnp +++ b/tests/example.capnp @@ -1,6 +1,6 @@ @0xd120e9a4c43868ab; -using C = import "../compiler/c.capnp"; +using C = import "/c.capnp"; $C.fieldgetset; diff --git a/tests/example.capnp.h b/tests/example.capnp.h index 9342d23..7a8fd17 100644 --- a/tests/example.capnp.h +++ b/tests/example.capnp.h @@ -7,6 +7,8 @@ #error "version mismatch between capnp_c.h and generated code" #endif +#include "c.capnp.h" + #ifdef __cplusplus extern "C" { #endif From 531eefc3cc18f2e323ab9c4a26d842a6b7e078c5 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Mon, 27 Mar 2017 03:30:37 +0100 Subject: [PATCH 09/13] Rewrite tests/example-test.cpp to use addressbook example from capnproto C++ project. --- Makefile.am | 6 +- README.md | 8 +- tests/addressbook.capnp | 58 +++++++++++ tests/addressbook.capnp.c | 200 ++++++++++++++++++++++++++++++++++++++ tests/addressbook.capnp.h | 134 +++++++++++++++++++++++++ tests/example-test.cpp | 102 +++++++++++++------ tests/example.capnp | 10 -- tests/example.capnp.c | 66 ------------- tests/example.capnp.h | 56 ----------- 9 files changed, 474 insertions(+), 166 deletions(-) create mode 100644 tests/addressbook.capnp create mode 100644 tests/addressbook.capnp.c create mode 100644 tests/addressbook.capnp.h delete mode 100644 tests/example.capnp delete mode 100644 tests/example.capnp.c delete mode 100644 tests/example.capnp.h diff --git a/Makefile.am b/Makefile.am index edf8d95..7847d78 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,19 +63,19 @@ capn_test_SOURCES = \ tests/capn-test.cpp \ tests/capn-stream-test.cpp \ tests/example-test.cpp \ - tests/example.capnp.c \ + tests/addressbook.capnp.c \ compiler/test.capnp.c \ compiler/schema-test.cpp \ compiler/schema.capnp.c noinst_HEADERS += \ compiler/test.capnp.h \ - tests/example.capnp.h + tests/addressbook.capnp.h EXTRA_DIST += \ compiler/c.capnp \ compiler/c++.capnp \ compiler/schema.capnp \ compiler/test.capnp \ - tests/example.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) diff --git a/README.md b/README.md index d12cd5d..8b46dd2 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,9 @@ struct MyStruct {} ### Example C code -See the unit tests in [`tests/example-test.cpp`](tests/example-test.cpp). The example schema file is [`tests/example.capnp`](tests/example.capnp). The tests are written in C++, but only use C features. +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: @@ -66,7 +68,9 @@ You need to compile these runtime library files and link them into your own proj * [`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. +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 diff --git a/tests/addressbook.capnp b/tests/addressbook.capnp new file mode 100644 index 0000000..faedaa0 --- /dev/null +++ b/tests/addressbook.capnp @@ -0,0 +1,58 @@ +# From 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); +} + diff --git a/tests/addressbook.capnp.c b/tests/addressbook.capnp.c new file mode 100644 index 0000000..db2ad3c --- /dev/null +++ b/tests/addressbook.capnp.c @@ -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); +} diff --git a/tests/addressbook.capnp.h b/tests/addressbook.capnp.h new file mode 100644 index 0000000..80be6c8 --- /dev/null +++ b/tests/addressbook.capnp.h @@ -0,0 +1,134 @@ +#ifndef CAPN_9EB32E19F86EE174 +#define CAPN_9EB32E19F86EE174 +/* AUTO GENERATED - DO NOT EDIT */ +#include + +#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 diff --git a/tests/example-test.cpp b/tests/example-test.cpp index 4c4f202..39e31b0 100644 --- a/tests/example-test.cpp +++ b/tests/example-test.cpp @@ -12,34 +12,63 @@ #include #include "capnp_c.h" -#include "example.capnp.h" +#include "addressbook.capnp.h" -TEST(Examples, RoundTrip) { +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); + +TEST(Examples, RoundTripPerson) { uint8_t buf[4096]; ssize_t sz = 0; - const char *s = "Hello."; + 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 `g`. - const capn_text capn_val0 = { - .len = (int) strlen(s), - .str = s, - .seg = NULL - }; - struct Greeting g = { - .text = capn_val0, - .timesToSay = 17, + // 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); - // Serialize `g` to `buf[0..sz-1]`. - struct capn c; - capn_init_malloc(&c); - capn_ptr cr = capn_root(&c); - struct capn_segment *cs = cr.seg; - Greeting_ptr gp = new_Greeting(cs); - write_Greeting(&g, gp); - int setp_ret = capn_setp(capn_root(&c), 0, gp.p); + 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); @@ -47,7 +76,7 @@ TEST(Examples, RoundTrip) { { // Write serialized object to file system. - FILE *f = fopen("tests/example-test.cpp.Greeting.out", "wb"); + 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); @@ -55,18 +84,33 @@ TEST(Examples, RoundTrip) { } { - // Deserialize `buf[0..sz-1]` to `rg`. + // 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); - Greeting_ptr rroot; - struct Greeting rg; + Person_ptr rroot; + struct Person rp; rroot.p = capn_getp(capn_root(&rc), 0 /* off */, 1 /* resolve */); - read_Greeting(&rg, rroot); + read_Person(&rp, rroot); - // Assert deserialized values in `rg` - EXPECT_EQ(rg.timesToSay, (uint32_t) 17); - EXPECT_EQ(strlen(s), (uint32_t) rg.text.len); - EXPECT_EQ(0, strncmp(s, rg.text.str, strlen(s))); + // 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); + + 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); } } + +// TODO: Accessor read/write vs read_/write_. diff --git a/tests/example.capnp b/tests/example.capnp deleted file mode 100644 index cbf7c45..0000000 --- a/tests/example.capnp +++ /dev/null @@ -1,10 +0,0 @@ -@0xd120e9a4c43868ab; - -using C = import "/c.capnp"; - -$C.fieldgetset; - -struct Greeting { - text @0 :Text = "Default greeting: hello world!"; - timesToSay @1 :UInt32; -} diff --git a/tests/example.capnp.c b/tests/example.capnp.c deleted file mode 100644 index 0c4dfed..0000000 --- a/tests/example.capnp.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "example.capnp.h" -/* AUTO GENERATED - DO NOT EDIT */ -static const capn_text capn_val0 = {0,"",0}; -static const uint8_t capn_buf[32] = { - 68,101,102,97,117,108,116,32, - 103,114,101,101,116,105,110,103, - 58,32,104,101,108,108,111,32, - 119,111,114,108,100,33,0,0 -}; -static const struct capn_segment capn_seg = {{0},0,0,0,(char*)&capn_buf[0],32,32,0}; -static capn_text capn_val1 = {30,(char*)&capn_buf[0],(struct capn_segment*)&capn_seg}; - -Greeting_ptr new_Greeting(struct capn_segment *s) { - Greeting_ptr p; - p.p = capn_new_struct(s, 8, 1); - return p; -} -Greeting_list new_Greeting_list(struct capn_segment *s, int len) { - Greeting_list p; - p.p = capn_new_list(s, len, 8, 1); - return p; -} -void read_Greeting(struct Greeting *s, Greeting_ptr p) { - capn_resolve(&p.p); - s->text = capn_get_text(p.p, 0, capn_val1); - s->timesToSay = capn_read32(p.p, 0); -} -void write_Greeting(const struct Greeting *s, Greeting_ptr p) { - capn_resolve(&p.p); - capn_set_text(p.p, 0, (s->text.str != capn_val1.str) ? s->text : capn_val0); - capn_write32(p.p, 0, s->timesToSay); -} -void get_Greeting(struct Greeting *s, Greeting_list l, int i) { - Greeting_ptr p; - p.p = capn_getp(l.p, i, 0); - read_Greeting(s, p); -} -void set_Greeting(const struct Greeting *s, Greeting_list l, int i) { - Greeting_ptr p; - p.p = capn_getp(l.p, i, 0); - write_Greeting(s, p); -} - -capn_text Greeting_get_text(Greeting_ptr p) -{ - capn_text text; - text = capn_get_text(p.p, 0, capn_val1); - return text; -} - -uint32_t Greeting_get_timesToSay(Greeting_ptr p) -{ - uint32_t timesToSay; - timesToSay = capn_read32(p.p, 0); - return timesToSay; -} - -void Greeting_set_text(Greeting_ptr p, capn_text text) -{ - capn_set_text(p.p, 0, (text.str != capn_val1.str) ? text : capn_val0); -} - -void Greeting_set_timesToSay(Greeting_ptr p, uint32_t timesToSay) -{ - capn_write32(p.p, 0, timesToSay); -} diff --git a/tests/example.capnp.h b/tests/example.capnp.h deleted file mode 100644 index 7a8fd17..0000000 --- a/tests/example.capnp.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef CAPN_D120E9A4C43868AB -#define CAPN_D120E9A4C43868AB -/* AUTO GENERATED - DO NOT EDIT */ -#include - -#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 Greeting; - -typedef struct {capn_ptr p;} Greeting_ptr; - -typedef struct {capn_ptr p;} Greeting_list; - -struct Greeting { - capn_text text; - uint32_t timesToSay; -}; - -static const size_t Greeting_word_count = 1; - -static const size_t Greeting_pointer_count = 1; - -static const size_t Greeting_struct_bytes_count = 16; - -capn_text Greeting_get_text(Greeting_ptr p); - -uint32_t Greeting_get_timesToSay(Greeting_ptr p); - -void Greeting_set_text(Greeting_ptr p, capn_text text); - -void Greeting_set_timesToSay(Greeting_ptr p, uint32_t timesToSay); - -Greeting_ptr new_Greeting(struct capn_segment*); - -Greeting_list new_Greeting_list(struct capn_segment*, int len); - -void read_Greeting(struct Greeting*, Greeting_ptr); - -void write_Greeting(const struct Greeting*, Greeting_ptr); - -void get_Greeting(struct Greeting*, Greeting_list, int i); - -void set_Greeting(const struct Greeting*, Greeting_list, int i); - -#ifdef __cplusplus -} -#endif -#endif From f7cd5685aae3c637ce4ccf44b363efc7c37e61a7 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Mon, 27 Mar 2017 03:33:34 +0100 Subject: [PATCH 10/13] Add comiler/c.capnp.h to Makefile.am noinst_HEADERS. --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index 7847d78..6fa4b95 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,6 +43,7 @@ noinst_HEADERS += \ lib/capnp_priv.h \ compiler/str.h \ compiler/schema.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 953031233ba3c8d9d720db40f0b3499f29744113 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Mon, 27 Mar 2017 04:20:38 +0100 Subject: [PATCH 11/13] Add example that uses accessor functions. --- tests/example-test.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/tests/example-test.cpp b/tests/example-test.cpp index 39e31b0..d2f8386 100644 --- a/tests/example-test.cpp +++ b/tests/example-test.cpp @@ -31,6 +31,12 @@ static capn_text chars_to_text(const char *chars) { 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; @@ -113,4 +119,38 @@ TEST(Examples, RoundTripPerson) { } } -// TODO: Accessor read/write vs read_/write_. +// 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)); + } +} From a80f24583eb97b74a27f468d0cf8a6755a03d889 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Thu, 30 Mar 2017 14:33:15 +0100 Subject: [PATCH 12/13] Add some missing capn_free() calls to the example test. --- tests/example-test.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/example-test.cpp b/tests/example-test.cpp index d2f8386..e16855a 100644 --- a/tests/example-test.cpp +++ b/tests/example-test.cpp @@ -45,12 +45,12 @@ TEST(Examples, RoundTripPerson) { 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; - { + 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, @@ -116,6 +116,8 @@ TEST(Examples, RoundTripPerson) { 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); } } @@ -153,4 +155,6 @@ TEST(Examples, PersonWithAccessors) { pn0.p = capn_getp(pnl.p, 0 /* offset */, 0 /* resolve */); EXPECT_EQ(Person_PhoneNumber_Type_home, Person_PhoneNumber_get_type(pn0)); } + + capn_free(&c); } From 4380d283f47428a0670fa9c88d32348d0598b9e1 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Sun, 2 Apr 2017 23:59:05 +0100 Subject: [PATCH 13/13] Add URL for original addressbook example; example to assert list length with capn_len(). --- tests/addressbook.capnp | 3 ++- tests/example-test.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/addressbook.capnp b/tests/addressbook.capnp index faedaa0..c2b85f4 100644 --- a/tests/addressbook.capnp +++ b/tests/addressbook.capnp @@ -1,4 +1,5 @@ -# From https://github.com/sandstorm-io/capnproto/blob/6816634a08b08bc8f52b4ee809afb58389f19655/c%2B%2B/samples/addressbook.capnp +# 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: diff --git a/tests/example-test.cpp b/tests/example-test.cpp index e16855a..10f0ff8 100644 --- a/tests/example-test.cpp +++ b/tests/example-test.cpp @@ -1,6 +1,9 @@ /* example-test.cpp * - * Some simple examples using c-capnproto + * 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 * @@ -107,6 +110,8 @@ TEST(Examples, RoundTripPerson) { 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);