Merge pull request #3832 from mikkelfj/c_docs
authorWouter van Oortmerssen <wvo@google.com>
Fri, 8 Apr 2016 17:54:27 +0000 (10:54 -0700)
committerWouter van Oortmerssen <wvo@google.com>
Fri, 8 Apr 2016 17:54:27 +0000 (10:54 -0700)
Documentation for C bindings

docs/source/CUsage.md [new file with mode: 0644]
docs/source/FlatBuffers.md
docs/source/Support.md
docs/source/Tutorial.md
docs/source/doxyfile
docs/source/doxygen_layout.xml
readme.md

diff --git a/docs/source/CUsage.md b/docs/source/CUsage.md
new file mode 100644 (file)
index 0000000..9aafa6f
--- /dev/null
@@ -0,0 +1,224 @@
+Use in C    {#flatbuffers_guide_use_c}
+==========
+
+The C language binding exists in a separate project named [FlatCC](https://github.com/dvidelabs/flatcc).
+
+The `flatcc` C schema compiler can generate code offline as well as
+online via a C library. It can also generate buffer verifiers and fast
+JSON parsers, printers.
+
+Great care has been taken to ensure compatibily with the main `flatc`
+project.
+
+## General Documention
+
+- [Tutorial](@ref flatbuffers_guide_tutorial) - select C as language
+  when scrolling down
+- [FlatCC Guide](https://github.com/dvidelabs/flatcc#flatcc-flatbuffers-in-c-for-c)
+- [The C Builder Interface](https://github.com/dvidelabs/flatcc/blob/master/doc/builder.md#the-builder-interface)
+- [The Monster Sample in C](https://github.com/dvidelabs/flatcc/blob/master/samples/monster/monster.c)
+- [GitHub](https://github.com/dvidelabs/flatcc)
+
+
+## Supported Platforms
+
+- Ubuntu (clang / gcc, ninja / gnu make)
+- OS-X (clang / gcc, ninja / gnu make)
+- Windows MSVC 2010, 2013, 2015
+
+CI builds recent versions of gcc, clang and MSVC on OS-X, Ubuntu, and
+Windows, and occasionally older compiler versions. See main project [Status](https://github.com/dvidelabs/flatcc#status).
+
+Other platforms may well work, including Centos, but are not tested
+regularly.
+
+The monster sample project was specifically written for C99 in order to
+follow the C++ version and for that reason it will not work with MSVC
+2010.
+
+## Modular Object Creation
+
+In the tutorial we used the call `Monster_create_as_root` to create the
+root buffer object since this is easier in simple use cases. Sometimes
+we need more modularity so we can reuse a function to create nested
+tables and root tables the same way. For this we need the
+`flatcc_builder_buffer_create_call`. It is best to keep `flatcc_builder`
+calls isolated at the top driver level, so we get:
+
+<div class="language-c">
+~~~{.c}
+  ns(Monster_ref_t) create_orc(flatcc_builder_t *B)
+  {
+    // ... same as in the tutorial.
+    return s(Monster_create(B, ...));
+  }
+
+  void create_monster_buffer()
+  {
+      uint8_t *buf;
+      size_t size;
+      flatcc_builder_t builder, *B;
+
+      // Initialize the builder object.
+      B = &builder;
+      flatcc_builder_init(B);
+      // Only use `buffer_create` without `create/start/end_as_root`.
+      flatcc_builder_buffer_create(create_orc(B));
+      // Allocate and copy buffer to user memory.
+      buf = flatcc_builder_finalize_buffer(B, &size);
+      // ... write the buffer to disk or network, or something.
+
+      free(buf);
+      flatcc_builder_clear(B);
+  }
+~~~
+</div>
+
+The same principle applies with `start/end` vs `start/end_as_root` in
+the top-down approach.
+
+
+## Top Down Example
+
+The tutorial uses a bottom up approach. In C it is also possible to use
+a top-down approach by starting and ending objects nested within each
+other. In the tutorial there is no deep nesting, so the difference is
+limited, but it shows the idea:
+
+<div class="language-c">
+<br>
+~~~{.c}
+  uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+  size_t treasure_count = c_vec_len(treasure);
+  ns(Weapon_ref_t) axe;
+
+  // NOTE: if we use end_as_root, we MUST also start as root.
+  ns(Monster_start_as_root(B));
+  ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f));
+  ns(Monster_hp_add(B, 300));
+  ns(Monster_mana_add(B, 150));
+  // We use create_str instead of add because we have no existing string reference.
+  ns(Monster_name_create_str(B, "Orc"));
+  // Again we use create because we no existing vector object, only a C-array.
+  ns(Monster_inventory_create(B, treasure, treasure_count));
+  ns(Monster_color_add(B, ns(Color_Red)));
+  if (1) {
+      ns(Monster_weapons_start(B));
+      ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Sword"), 3));
+      // We reuse the axe object later. Note that we dereference a pointer
+      // because push always returns a short-term pointer to the stored element.
+      // We could also have created the axe object first and simply pushed it.
+      axe = *ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Axe"), 5));
+      ns(Monster_weapons_end(B));
+  } else {
+      // We can have more control with the table elements added to a vector:
+      //
+      ns(Monster_weapons_start(B));
+      ns(Monster_weapons_push_start(B));
+      ns(Weapon_name_create_str(B, "Sword"));
+      ns(Weapon_damage_add(B, 3));
+      ns(Monster_weapons_push_end(B));
+      ns(Monster_weapons_push_start(B));
+      ns(Monster_weapons_push_start(B));
+      ns(Weapon_name_create_str(B, "Axe"));
+      ns(Weapon_damage_add(B, 5));
+      axe = *ns(Monster_weapons_push_end(B));
+      ns(Monster_weapons_end(B));
+  }
+  // Unions can get their type by using a type-specific add/create/start method.
+  ns(Monster_equipped_Weapon_add(B, axe));
+
+  ns(Monster_end_as_root(B));
+~~~
+</div>
+
+
+## Basic Reflection
+
+The C-API does support reading binary schema (.bfbs)
+files via code generated from the `reflection.fbs` schema, and an
+[example usage](https://github.com/dvidelabs/flatcc/tree/master/samples/reflection)
+shows how to use this. The reflection schema files are pre-generated
+in the [runtime distribution](https://github.com/dvidelabs/flatcc/tree/master/include/flatcc/reflection).
+
+
+## Mutations and Reflection
+
+The C-API does not support mutating reflection like C++ does, nor does
+the reader interface support mutating scalars (and it is generally
+unsafe to do so even after verification).
+
+The generated reader interface supports sorting vectors in-place after
+casting them to a mutating type because it is not practical to do so
+while building a buffer. This is covered in the builder documentation.  
+The reflection example makes use of this feature to look up objects by
+name.
+
+It is possible to build new buffers using complex objects from existing
+buffers as source. This can be very efficient due to direct copy
+semantics without endian conversion or temporary stack allocation.
+
+Scalars, structs and strings can be used as source, as well vectors of
+these.
+
+It is currently not possible to use an existing table or vector of table
+as source, but it would be possible to add support for this at some
+point.
+
+
+## Namespaces
+
+The `FLATBUFFERS_WRAP_NAMESPACE` approach used in the tutorial is convenient
+when each function has a very long namespace prefix. But it isn't always
+the best approach. If the namespace is absent, or simple and
+informative, we might as well use the prefix directly. The
+[reflection example](https://github.com/dvidelabs/flatcc/blob/master/samples/reflection/bfbs2json.c)
+mentioned above uses this approach.
+
+
+## Checking for Present Members
+
+Not all languages support testing if a field is present, but in C we can
+elaborate the reader section of the tutorial with tests for this. Recall
+that `mana` was set to the default value `150` and therefore shouldn't
+be present.
+
+<div class="language-c">
+~~~{.c}
+  int hp_present = ns(Monster_hp_is_present(monster)); // 1
+  int mana_present = ns(Monster_mana_is_present(monster)); // 0
+~~~
+</div>
+
+## Alternative ways to add a Union
+
+In the tutorial we used a single call to add a union.  Here we show
+different ways to accomplish the same thing. The last form is rarely
+used, but is the low-level way to do it. It can be used to group small
+values together in the table by adding type and data at different
+points in time.
+
+<div class="language-c">
+~~~{.c}
+   ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe));
+   ns(Monster_equipped_add(B, equipped));
+   // or alternatively
+   ns(Monster_equipped_Weapon_add(B, axe);
+   // or alternatively
+   ns(Monster_equipped_add_type(B, ns(Equipment_Weapon));
+   ns(Monster_equipped_add_member(B, axe));
+~~~
+</div>
+
+## Why not integrate with the `flatc` tool?
+
+[It was considered how the C code generator could be integrated into the
+`flatc` tool](https://github.com/dvidelabs/flatcc/issues/1), but it
+would either require that the standalone C implementation of the schema
+compiler was dropped, or it would lead to excessive code duplication, or
+a complicated intermediate representation would have to be invented.
+Neither of these alternatives are very attractive, and it isn't a big
+deal to use the `flatcc` tool instead of `flatc` given that the
+FlatBuffers C runtime library needs to be made available regardless.
+
+
index bbb0dce..46d4c12 100644 (file)
@@ -4,9 +4,9 @@ FlatBuffers    {#flatbuffers_index}
 # Overview {#flatbuffers_overview}
 
 [FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
-serialization library for C++, C#, Go, Java, JavaScript, PHP, and Python
-(C and Ruby in progress). It was originally created at Google for game
-development and other performance-critical applications.
+serialization library for C++, C#, C, Go, Java, JavaScript, PHP, and Python.
+It was originally created at Google for game development and other
+performance-critical applications.
 
 It is available as Open Source on [GitHub](http://github.com/google/flatbuffers)
 under the Apache license, v2 (see LICENSE.txt).
@@ -131,6 +131,8 @@ sections provide a more in-depth usage guide.
     in your own programs.
 -   How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
     own programs.
+-   How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your
+    own programs.
 -   [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
 -   Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
     using FlatBuffers.
index ba8c765..7bc3348 100755 (executable)
@@ -18,23 +18,23 @@ In general:
 
 NOTE: this table is a start, it needs to be extended.
 
-Feature                        | C++    | Java   | C#     | Go     | Python | JS        | C    | PHP | Ruby
------------------------------- | ------ | ------ | ------ | ------ | ------ | --------- | ---- | --- | ----
-Codegen for all basic features | Yes    | Yes    | Yes    | Yes    | Yes    | Yes       | WiP  | WiP | WiP
-JSON parsing                   | Yes    | No     | No     | No     | No     | No        | No   | No  | No
-Simple mutation                | Yes    | WIP    | WIP    | No     | No     | No        | No   | No  | No
-Reflection                     | Yes    | No     | No     | No     | No     | No        | No   | No  | No
-Buffer verifier                | Yes    | No     | No     | No     | No     | No        | No   | No  | No
-Testing: basic                 | Yes    | Yes    | Yes    | Yes    | Yes    | Yes       | ?    | ?   | ?
-Testing: fuzz                  | Yes    | No     | No     | Yes    | Yes    | No        | ?    | ?   | ?
-Performance:                   | Superb | Great  | Great  | Great  | Ok     | ?         |Superb| ?   | ?
-Platform: Windows              | VS2010 | Yes    | Yes    | ?      | ?      | ?         | ?    | ?   | ?
-Platform: Linux                | GCC282 | Yes    | ?      | Yes    | Yes    | ?         | ?    | ?   | ?
-Platform: OS X                 | Xcode4 | ?      | ?      | ?      | Yes    | ?         | ?    | ?   | ?
-Platform: Android              | NDK10d | Yes    | ?      | ?      | ?      | ?         | ?    | ?   | ?
-Platform: iOS                  | ?      | ?      | ?      | ?      | ?      | ?         | ?    | ?   | ?
-Engine: Unity                  | ?      | ?      | Yes    | ?      | ?      | ?         | ?    | ?   | ?
-Primary authors (github)       | gwvo   | gwvo   | ev*/js*| rw     | rw     | evanw/ev* | mik* | ch* | rw
+Feature                        | C++    | Java   | C#     | Go     | Python | JS        | C        | PHP | Ruby
+------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | ------  | --- | ----
+Codegen for all basic features | Yes    | Yes    | Yes    | Yes    | Yes    | Yes       | Yes     | WiP | WiP
+JSON parsing                   | Yes    | No     | No     | No     | No     | No        | Yes     | No  | No
+Simple mutation                | Yes    | WIP    | WIP    | No     | No     | No        | No      | No  | No
+Reflection                     | Yes    | No     | No     | No     | No     | No        | Basic   | No  | No
+Buffer verifier                | Yes    | No     | No     | No     | No     | No        | Yes     | No  | No
+Testing: basic                 | Yes    | Yes    | Yes    | Yes    | Yes    | Yes       | Yes     | ?   | ?
+Testing: fuzz                  | Yes    | No     | No     | Yes    | Yes    | No        | No      | ?   | ?
+Performance:                   | Superb | Great  | Great  | Great  | Ok     | ?         | Superb  | ?   | ?
+Platform: Windows              | VS2010 | Yes    | Yes    | ?      | ?      | ?         | VS2010  | ?   | ?
+Platform: Linux                | GCC282 | Yes    | ?      | Yes    | Yes    | ?         | Yes     | ?   | ?
+Platform: OS X                 | Xcode4 | ?      | ?      | ?      | Yes    | ?         | Yes     | ?   | ?
+Platform: Android              | NDK10d | Yes    | ?      | ?      | ?      | ?         | ?       | ?   | ?
+Platform: iOS                  | ?      | ?      | ?      | ?      | ?      | ?         | ?       | ?   | ?
+Engine: Unity                  | ?      | ?      | Yes    | ?      | ?      | ?         | ?       | ?   | ?
+Primary authors (github)       | gwvo   | gwvo   | ev*/js*| rw     | rw     | evanw/ev* | mik*    | ch* | rw
 
   * ev = evolutional
   * js = jonsimantov
index de1e9fd..1e48796 100644 (file)
@@ -19,7 +19,6 @@ character, the hero of the story, needs to slay some `orc`s. We will walk
 through each step necessary to create this monster type using FlatBuffers.
 
 Please select your desired language for our quest:
-
 \htmlonly
 <form>
   <input type="radio" name="language" value="cpp" checked="checked">C++</input>
@@ -29,6 +28,7 @@ Please select your desired language for our quest:
   <input type="radio" name="language" value="python">Python</input>
   <input type="radio" name="language" value="javascript">JavaScript</input>
   <input type="radio" name="language" value="php">PHP</input>
+  <input type="radio" name="language" value="c">C</input>
 </form>
 \endhtmlonly
 
@@ -98,6 +98,10 @@ Samples demonstating the concepts in this example are located in the source code
 package, under the `samples` directory. You can browse the samples on GitHub
 [here](https://github.com/google/flatbuffers/tree/master/samples).
 
+<div class="language-c">
+*Note: The above does not apply to C, instead [look here](https://github.com/dvidelabs/flatcc/tree/master/samples).*
+</div>
+
 For your chosen language, please cross-reference with:
 
 <div class="language-cpp">
@@ -121,6 +125,9 @@ For your chosen language, please cross-reference with:
 <div class="language-php">
 [SampleBinary.php](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.php)
 </div>
+<div class="language-c">
+[monster.c](https://github.com/dvidelabs/flatcc/blob/master/samples/monster/monster.c)
+</div>
 
 ## Writing the Monsters' FlatBuffer Schema
 
@@ -225,6 +232,15 @@ FlatBuffer compiler.
 
 Once `flatc` is built successfully, compile the schema for your language:
 
+<div class="language-c">
+*Note: If you're working in C, you need to use the separate project [FlatCC](https://github.com/dvidelabs/flatcc) which contains a schema compiler and runtime library in C for C.*
+<br>
+See [flatcc build instructions](https://github.com/dvidelabs/flatcc#building).
+<br>
+Please be aware of the difference between `flatc` and `flatcc` tools.
+<br>
+</div>
+
 <div class="language-cpp">
 ~~~{.sh}
   cd flatbuffers/sample
@@ -267,8 +283,17 @@ Once `flatc` is built successfully, compile the schema for your language:
   ./../flatc --php samples/monster.fbs
 ~~~
 </div>
+<div class="language-c">
+~~~{.sh}
+  cd flatcc
+  mkdir -p build/tmp/samples/monster
+  bin/flatcc -a -o build/tmp/samples/monster samples/monster/monster.fbs
+  # or just
+  flatcc/samples/monster/build.sh
+~~~
+</div>
 
-For a more complete guide to using the `flatc` compiler, pleaes read the
+For a more complete guide to using the `flatc` compiler, please read the
 [Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
 section of the Programmer's Guide.
 
@@ -359,6 +384,18 @@ The first step is to import/include the library, generated files, etc.
   }
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  #include "monster_builder.h" // Generated by `flatcc`.
+
+  // Convenient namespace macro to manage long namespace prefix.
+  #undef ns
+  #define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) // Specified in the schema.
+
+  // A helper to simplify creating vectors from C-arrays.
+  #define c_vec_len(V) (sizeof(V)/sizeof((V)[0]))
+~~~
+</div>
 
 Now we are ready to start building some buffers. In order to start, we need
 to create an instance of the `FlatBufferBuilder`, which will contain the buffer
@@ -413,6 +450,14 @@ as it grows:
   $builder = new Google\FlatBuffers\FlatbufferBuilder(0);
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+    flatcc_builder_t builder, *B;
+    B = &builder;
+    // Initialize the builder object.
+    flatcc_builder_init(B);
+~~~
+</div>
 
 After creating the `builder`, we can start serializing our data. Before we make
 our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
@@ -525,6 +570,18 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
   $weapons = \MyGame\Sample\Monster::CreateWeaponsVector($builder, $weaps);
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  ns(Weapon_ref_t) weapon_one_name = flatbuffers_string_create_str(B, "Sword");
+  uint16_t weapon_one_damage = 3;
+
+  ns(Weapon_ref_t) weapon_two_name = flatbuffers_string_create_str(B, "Axe");
+  uint16_t weapon_two_damage = 5;
+
+  ns(Weapon_ref_t) sword = ns(Weapon_create(B, weapon_one_name, weapon_one_damage));
+  ns(Weapon_ref_t) axe = ns(Weapon_create(B, weapon_two_name, weapon_two_damage));
+~~~
+</div>
 
 Now let's create our monster, the `orc`. For this `orc`, lets make him
 `red` with rage, positioned at `(1.0, 2.0, 3.0)`, and give him
@@ -627,6 +684,20 @@ traversal. This is generally easy to do on any tree structures.
   $inv = \MyGame\Sample\Monster::CreateInventoryVector($builder, $treasure);
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  // Serialize a name for our monster, called "Orc".
+  // The _str suffix indicates the source is an ascii-z string.
+  flatbuffers_string_ref_t name = flatbuffers_string_create_str(B, "Orc");
+
+  // Create a `vector` representing the inventory of the Orc. Each number
+  // could correspond to an item that can be claimed after he is slain.
+  uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+  flatbuffers_uint8_vec_ref_t inventory;
+  // `c_vec_len` is the convenience macro we defined earlier.
+  inventory = flatbuffers_uint8_vec_create(B, treasure, c_vec_len(treasure));
+~~~
+</div>
 
 We serialized two built-in data types (`string` and `vector`) and captured
 their return values. These values are offsets into the serialized data,
@@ -709,8 +780,18 @@ offsets.
   $weapons = \MyGame\Sample\Monster::CreateWeaponsVector($builder, $weaps);
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  // We use the internal builder stack to implement a dynamic vector.
+  ns(Weapon_vec_start(B));
+  ns(Weapon_vec_push(B, sword));
+  ns(Weapon_vec_push(B, axe));
+  ns(Weapon_vec_ref_t) weapons = ns(Weapon_vec_end(B));
+~~~
+</div>
 
-To create a `struct`, use the `Vec3` class/struct that was generated by `flatc`:
+To create a `struct`, use the `Vec3` class/struct that was generated by
+the schema compiler:
 
 <div class="language-cpp">
 ~~~{.cpp}
@@ -754,6 +835,12 @@ To create a `struct`, use the `Vec3` class/struct that was generated by `flatc`:
   $pos = \MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0);
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  // Create a `Vec3`, representing the Orc's position in 3-D space.
+  ns(Vec3_t) pos = { 1.0f, 2.0f, 3.0f };
+~~~
+</div>
 
 We have now serialized the non-scalar components of the orc, so we
 can serialize the monster itself:
@@ -862,16 +949,29 @@ can serialize the monster itself:
   $orc = \MyGame\Sample\Monster::EndMonster($builder);
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  // Set his hit points to 300 and his mana to 150.
+  uint16_t hp = 300;
+  uint16_t mana = 150;
 
-<div class="language-cpp">
-<br>
-*Note: Since we passing `150` as the `mana` field, which happens to be the
+  // Define an equipment union. `create` calls in C has a single
+  // argument for unions where C++ has both a type and a data argument.
+  ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe));
+  ns(Monster_create_as_root(B, &pos, mana, hp, name, inventory, ns(Color_Red),
+          weapons, equipped));
+~~~
+</div>
+
+*Note: Since we are passing `150` as the `mana` field, which happens to be the
 default value, the field will not actually be written to the buffer, since the
 default value will be returned on query anyway. This is a nice space savings,
 especially if default values are common in your data. It also means that you do
 not need to be worried of adding a lot of fields that are only used in a small
 number of instances, as it will not bloat the buffer if unused.*
-<br><br>
+
+<div class="language-cpp">
+<br>
 If you do not wish to set every field in a `table`, it may be more convenient to
 manually set each field of your monster, instead of calling `CreateMonster()`.
 The following snippet is functionally equivalent to the above code, but provides
@@ -892,6 +992,31 @@ a bit more flexibility.
   auto orc = monster_builder.Finish();
 ~~~
 </div>
+<div class="language-c">
+If you do not wish to set every field in a `table`, it may be more convenient to
+manually set each field of your monster, instead of calling `create_monster_as_root()`.
+The following snippet is functionally equivalent to the above code, but provides
+a bit more flexibility.
+<br>
+~~~{.c}
+  // It is important to pair `start_as_root` with `end_as_root`.
+  ns(Monster_start_as_root(B));
+  ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f));
+  // or alternatively
+  //ns(Monster_pos_add(&pos);
+
+  ns(Monster_hp_add(B, hp));
+  // Notice that `Monser_name_add` adds a string reference unlike the
+  // add_str and add_strn variants.
+  ns(Monster_name_add(B, name));
+  ns(Monster_inventory_add(B, inventory));
+  ns(Monster_color_add(B, ns(Color_Red)));
+  ns(Monster_weapons_add(B, weapons));
+  ns(Monster_equipped_add(B, equipped));
+  // Complete the monster object and make it the buffer root object.
+  ns(Monster_end_as_root(B));
+~~~
+</div>
 
 Before finishing the serialization, let's take a quick look at FlatBuffer
 `union Equipped`. There are two parts to each FlatBuffer `union`. The first, is
@@ -947,11 +1072,18 @@ Here is a repetition these lines, to help highlight them more clearly:
     \MyGame\Sample\Monster::AddEquipped($builder, $axe); // Union data
   ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  // Add union type and data simultanously.
+  ns(Monster_equipped_Weapon_add(B, axe)); 
+~~~
+</div>
 
 After you have created your buffer, you will have the offset to the root of the
 data in the `orc` variable, so you can finish the buffer by calling the
 appropriate `finish` method.
 
+
 <div class="language-cpp">
 ~~~{.cpp}
   // Call `Finish()` to instruct the builder that this monster is complete.
@@ -999,6 +1131,11 @@ appropriate `finish` method.
                            //                        $builder, $orc);`.
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  // Because we used `Monster_create_as_root`, we do not need a `finish` call in C`.
+~~~
+</div>
 
 The buffer is now ready to be stored somewhere, sent over the network, be
 compressed, or whatever you'd like to do with it. You can access the buffer
@@ -1048,6 +1185,29 @@ like so:
   $buf = $builder->dataBuffer(); // Of type `Google\FlatBuffers\ByteBuffer`
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  uint8_t *buf;
+  size_t size;
+
+  // Allocate and extract a readable buffer from internal builder heap.
+  // The returned buffer must be deallocated using `free`.
+  // NOTE: Finalizing the buffer does NOT change the builder, it
+  // just creates a snapshot of the builder content.
+  buf = flatcc_builder_finalize_buffer(B, &size);
+  // use buf
+  free(buf);
+
+  // Optionally reset builder to reuse builder without deallocating
+  // internal stack and heap.
+  flatcc_builder_reset(B);
+  // build next buffer.
+  // ...
+
+  // Cleanup.
+  flatcc_builder_clear(B);
+~~~
+</div>
 
 #### Reading Orc FlatBuffers
 
@@ -1055,7 +1215,7 @@ Now that we have successfully created an `Orc` FlatBuffer, the monster data can
 be saved, sent over a network, etc. Let's now adventure into the inverse, and
 deserialize a FlatBuffer.
 
-This seciton requires the same import/include, namespace, etc. requirements as
+This section requires the same import/include, namespace, etc. requirements as
 before:
 
 <div class="language-cpp">
@@ -1134,6 +1294,15 @@ before:
   }
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  // Only needed if we don't have `#include "monster_builder.h"`.
+  #include "monster_reader.h"
+
+  #undef ns
+  #define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) // Specified in the schema.
+~~~
+</div>
 
 Then, assuming you have a variable containing to the bytes of data from disk,
 network, etc., you can create a monster from this data:
@@ -1224,8 +1393,18 @@ network, etc., you can create a monster from this data:
   $monster = \MyGame\Sample\Monster::GetRootAsMonster($buf);
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  // Note that we use the `table_t` suffix when reading a table object
+  // as opposed to the `ref_t` suffix used during the construction of
+  // the buffer.
+  ns(Monster_table_t) monster = ns(Monster_as_root(buffer));
 
-If you look in the generated files from `flatc`, you will see it generated
+  // Note: root object pointers are NOT the same as the `buffer` pointer.
+~~~
+</div>
+
+If you look in the generated files from the schema compiler, you will see it generated
 accessors for all non-`deprecated` fields. For example:
 
 <div class="language-cpp">
@@ -1279,10 +1458,17 @@ accessors for all non-`deprecated` fields. For example:
   $name = monster->getName();
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  uint16_t hp = ns(Monster_hp(monster));
+  uint16_t mana = ns(Monster_mana(monster));
+  flatbuffers_string_t name = ns(Monster_name(monster));
+~~~
+</div>
 
 These should hold `300`, `150`, and `"Orc"` respectively.
 
-*Note: We never stored a value in `mp`, so we got the default value of `150`.*
+*Note: The default value `150` wasn't stored in `mana`, but we are still able to retrieve it.*
 
 To access sub-objects, in the case of our `pos`, which is a `Vec3`:
 
@@ -1348,10 +1534,18 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
   $z = $pos->getZ();
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  ns(Vec3_struct_t) pos = ns(Monster_pos(monster));
+  float x = ns(Vec3_x(pos));
+  float y = ns(Vec3_y(pos));
+  float z = ns(Vec3_z(pos));
+~~~
+</div>
 
 `x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively.
 
-*Note: Had we not set `pos` during serialization, it would be `NULL`-value.*
+*Note: Had we not set `pos` during serialization, it would be `NULL`-value.*
 
 Similarly, we can access elements of the inventory `vector` by indexing it. You
 can also iterate over the length of the array/vector representing the
@@ -1400,6 +1594,14 @@ FlatBuffers `vector`.
   $third_item = $monster->getInventory(2);
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+    // If `inv` hasn't been set, it will be null. It is valid get
+    // the length of null which will be 0, useful for iteration.
+    flatbuffers_uint8_vec_t inv = ns(Monster_inventory(monster));
+    size_t inv_len = flatbuffers_uint8_vec_len(inv);
+~~~
+</div>
 
 For `vector`s of `table`s, you can access the elements like any other vector,
 except your need to handle the result as a FlatBuffer `table`:
@@ -1458,6 +1660,15 @@ except your need to handle the result as a FlatBuffer `table`:
   $second_weapon_damage = $monster->getWeapons(1)->getDamage();
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  ns(Weapon_vec_t) weapons = ns(Monster_weapons(monster));
+  size_t weapons_len = ns(Weapon_vec_len(weapons));
+  // We can use `const char *` instead of `flatbuffers_string_t`.
+  const char *second_weapon_name = ns(Weapon_name(ns(Weapon_vec_at(weapons, 1))));
+  uint16_t second_weapon_damage =  ns(Weapon_damage(ns(Weapon_vec_at(weapons, 1))));
+~~~
+</div>
 
 Last, we can access our `Equipped` FlatBuffer `union`. Just like when we created
 the `union`, we need to get both parts of the `union`: the type and the data.
@@ -1560,6 +1771,18 @@ We can access the type to dynamically cast the data as needed (since the
   }
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  // Access union type field.
+  if (ns(Monster_equipped_type(monster)) == ns(Equipment_Weapon)) {
+      // Cast to appropriate type:
+      // C allows for silent void pointer assignment, so we need no explicit cast.
+      ns(Weapon_table_t) weapon = ns(Monster_equipped(monster));
+      const char *weapon_name = ns(Weapon_name(weapon)); // "Axe"
+      uint16_t weapon_damage = ns(Weapon_damage(weapon)); // 5
+  }
+~~~
+</div>
 
 ## Mutating FlatBuffers
 
@@ -1624,6 +1847,12 @@ mutators like so:
   <API for mutating FlatBuffers is not yet supported in PHP.>
 ~~~
 </div>
+<div class="language-c">
+~~~{.c}
+  <API for in-place mutating FlatBuffers will not be supported in C
+  (except in-place vector sorting is possible).>
+~~~
+</div>
 
 We use the somewhat verbose term `mutate` instead of `set` to indicate that this
 is a special use case, not to be confused with the default way of constructing
@@ -1687,6 +1916,14 @@ FlatBuffer binary representation of the contents from our `.json` file.
 [Use in C++](@ref flatbuffers_guide_use_cpp) section of the Programmer's
 Guide for more information.*
 </div>
+<div class="language-c">
+*Note: If you're working in C, the `flatcc --json` (not `flatc`)
+compiler will generate schema specific high performance json parsers and
+printers that you can compile and use at runtime. The `flatc` compiler (not
+`flatcc`) on the other hand, is still useful for general offline json to
+flatbuffer conversion from a given schema. There are no current plans
+for `flatcc` to support this.*
+</div>
 
 ## Advanced Features for Each Language
 
@@ -1716,5 +1953,8 @@ For your chosen language, see:
 <div class="language-php">
 [Use in PHP](@ref flatbuffers_guide_use_php)
 </div>
+<div class="language-c">
+[Use in C](@ref flatbuffers_guide_use_c)
+</div>
 
 <br>
index ba6fbcb..bef63f5 100755 (executable)
@@ -750,6 +750,7 @@ INPUT = "FlatBuffers.md" \
         "Compiler.md" \
         "Schemas.md" \
         "CppUsage.md" \
+        "CUsage.md" \
         "GoUsage.md" \
         "JavaCsharpUsage.md" \
         "JavaScriptUsage.md" \
index 1437016..b5d8644 100644 (file)
@@ -25,6 +25,8 @@
           title="Writing a schema"/>
       <tab type="user" url="@ref flatbuffers_guide_use_cpp"
           title="Use in C++"/>
+      <tab type="user" url="@ref flatbuffers_guide_use_c"
+          title="Use in C"/>
       <tab type="user" url="@ref flatbuffers_guide_use_go"
           title="Use in Go"/>
       <tab type="user" url="@ref flatbuffers_guide_use_java_c-sharp"
index 9546048..15dd41b 100755 (executable)
--- a/readme.md
+++ b/readme.md
@@ -15,6 +15,7 @@ unpacking/parsing it first, while still having great forwards/backwards compatib
 ## Supported programming languages
 * C++
 * C#
+* C
 * Go
 * Java
 * JavaScript