1 Tutorial {#flatbuffers_guide_tutorial} 2 ======== 3 4 ## Overview 5 6 This tutorial provides a basic example of how to work with 7 [FlatBuffers](@ref flatbuffers_overview). We will step through a simple example 8 application, which shows you how to: 9 10 - Write a FlatBuffer `schema` file. 11 - Use the `flatc` FlatBuffer compiler. 12 - Parse [JSON](http://json.org) files that conform to a schema into 13 FlatBuffer binary files. 14 - Use the generated files in many of the supported languages (such as C++, 15 Java, and more.) 16 17 During this example, imagine that you are creating a game where the main 18 character, the hero of the story, needs to slay some `orc`s. We will walk 19 through each step necessary to create this monster type using FlatBuffers. 20 21 Please select your desired language for our quest: 22 \htmlonly 23 <form> 24 <input type="radio" name="language" value="cpp" checked="checked">C++</input> 25 <input type="radio" name="language" value="java">Java</input> 26 <input type="radio" name="language" value="csharp">C#</input> 27 <input type="radio" name="language" value="go">Go</input> 28 <input type="radio" name="language" value="python">Python</input> 29 <input type="radio" name="language" value="javascript">JavaScript</input> 30 <input type="radio" name="language" value="php">PHP</input> 31 <input type="radio" name="language" value="c">C</input> 32 </form> 33 \endhtmlonly 34 35 \htmlonly 36 <script> 37 /** 38 * Check if an HTML `class` attribute is in the language-specific format. 39 * @param {string} languageClass An HTML `class` attribute in the format 40 * 'language-{lang}', where {lang} is a programming language (e.g. 'cpp', 41 * 'java', 'go', etc.). 42 * @return {boolean} Returns `true` if `languageClass` was in the valid 43 * format, prefixed with 'language-'. Otherwise, it returns false. 44 */ 45 function isProgrammingLanguageClassName(languageClass) { 46 if (languageClass && languageClass.substring(0, 9) == 'language-' && 47 languageClass.length > 8) { 48 return true; 49 } else { 50 return false; 51 } 52 } 53 54 /** 55 * Given a language-specific HTML `class` attribute, extract the language. 56 * @param {string} languageClass The string name of an HTML `class` attribute, 57 * in the format `language-{lang}`, where {lang} is a programming language 58 * (e.g. 'cpp', 'java', 'go', etc.). 59 * @return {string} Returns a string containing only the {lang} portion of 60 * the class name. If the input was invalid, then it returns `null`. 61 */ 62 function extractProgrammingLanguageFromLanguageClass(languageClass) { 63 if (isProgrammingLanguageClassName(languageClass)) { 64 return languageClass.substring(9); 65 } else { 66 return null; 67 } 68 } 69 70 /** 71 * Hide every code snippet, except for the language that is selected. 72 */ 73 function displayChosenLanguage() { 74 var selection = $('input:checked').val(); 75 76 var htmlElements = document.getElementsByTagName('*'); 77 for (var i = 0; i < htmlElements.length; i++) { 78 if (isProgrammingLanguageClassName(htmlElements[i].className)) { 79 if (extractProgrammingLanguageFromLanguageClass( 80 htmlElements[i].className).toLowerCase() != selection) { 81 htmlElements[i].style.display = 'none'; 82 } else { 83 htmlElements[i].style.display = 'initial'; 84 } 85 } 86 } 87 } 88 89 $( document ).ready(displayChosenLanguage); 90 91 $('input[type=radio]').on("click", displayChosenLanguage); 92 </script> 93 \endhtmlonly 94 95 ## Where to Find the Example Code 96 97 Samples demonstating the concepts in this example are located in the source code 98 package, under the `samples` directory. You can browse the samples on GitHub 99 [here](https://github.com/google/flatbuffers/tree/master/samples). 100 101 <div class="language-c"> 102 *Note: The above does not apply to C, instead [look here](https://github.com/dvidelabs/flatcc/tree/master/samples).* 103 </div> 104 105 For your chosen language, please cross-reference with: 106 107 <div class="language-cpp"> 108 [sample_binary.cpp](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.cpp) 109 </div> 110 <div class="language-java"> 111 [SampleBinary.java](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.java) 112 </div> 113 <div class="language-csharp"> 114 [SampleBinary.cs](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.cs) 115 </div> 116 <div class="language-go"> 117 [sample_binary.go](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.go) 118 </div> 119 <div class="language-python"> 120 [sample_binary.py](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.py) 121 </div> 122 <div class="language-javascript"> 123 [samplebinary.js](https://github.com/google/flatbuffers/blob/master/samples/samplebinary.js) 124 </div> 125 <div class="language-php"> 126 [SampleBinary.php](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.php) 127 </div> 128 <div class="language-c"> 129 [monster.c](https://github.com/dvidelabs/flatcc/blob/master/samples/monster/monster.c) 130 </div> 131 132 ## Writing the Monsters' FlatBuffer Schema 133 134 To start working with FlatBuffers, you first need to create a `schema` file, 135 which defines the format for each data structure you wish to serialize. Here is 136 the `schema` that defines the template for our monsters: 137 138 ~~~ 139 // Example IDL file for our monster's schema. 140 141 namespace MyGame.Sample; 142 143 enum Color:byte { Red = 0, Green, Blue = 2 } 144 145 union Equipment { Weapon } // Optionally add more tables. 146 147 struct Vec3 { 148 x:float; 149 y:float; 150 z:float; 151 } 152 153 table Monster { 154 pos:Vec3; // Struct. 155 mana:short = 150; 156 hp:short = 100; 157 name:string; 158 friendly:bool = false (deprecated); 159 inventory:[ubyte]; // Vector of scalars. 160 color:Color = Blue; // Enum. 161 weapons:[Weapon]; // Vector of tables. 162 equipped:Equipment; // Union. 163 path:[Vec3]; // Vector of structs. 164 } 165 166 table Weapon { 167 name:string; 168 damage:short; 169 } 170 171 root_type Monster; 172 ~~~ 173 174 As you can see, the syntax for the `schema` 175 [Interface Definition Language (IDL)](https://en.wikipedia.org/wiki/Interface_description_language) 176 is similar to those of the C family of languages, and other IDL languages. Let's 177 examine each part of this `schema` to determine what it does. 178 179 The `schema` starts with a `namespace` declaration. This determines the 180 corresponding package/namespace for the generated code. In our example, we have 181 the `Sample` namespace inside of the `MyGame` namespace. 182 183 Next, we have an `enum` definition. In this example, we have an `enum` of type 184 `byte`, named `Color`. We have three values in this `enum`: `Red`, `Green`, and 185 `Blue`. We specify `Red = 0` and `Blue = 2`, but we do not specify an explicit 186 value for `Green`. Since the behavior of an `enum` is to increment if 187 unspecified, `Green` will receive the implicit value of `1`. 188 189 Following the `enum` is a `union`. The `union` in this example is not very 190 useful, as it only contains the one `table` (named `Weapon`). If we had created 191 multiple tables that we would want the `union` to be able to reference, we 192 could add more elements to the `union Equipment`. 193 194 After the `union` comes a `struct Vec3`, which represents a floating point 195 vector with `3` dimensions. We use a `struct` here, over a `table`, because 196 `struct`s are ideal for data structures that will not change, since they use 197 less memory and have faster lookup. 198 199 The `Monster` table is the main object in our FlatBuffer. This will be used as 200 the template to store our `orc` monster. We specify some default values for 201 fields, such as `mana:short = 150`. All unspecified fields will default to `0` 202 or `NULL`. Another thing to note is the line 203 `friendly:bool = false (deprecated);`. Since you cannot delete fields from a 204 `table` (to support backwards compatability), you can set fields as 205 `deprecated`, which will prevent the generation of accessors for this field in 206 the generated code. Be careful when using `deprecated`, however, as it may break 207 legacy code that used this accessor. 208 209 The `Weapon` table is a sub-table used within our FlatBuffer. It is 210 used twice: once within the `Monster` table and once within the `Equipment` 211 enum. For our `Monster`, it is used to populate a `vector of tables` via the 212 `weapons` field within our `Monster`. It is also the only table referenced by 213 the `Equipment` union. 214 215 The last part of the `schema` is the `root_type`. The root type declares what 216 will be the root table for the serialized data. In our case, the root type is 217 our `Monster` table. 218 219 The scalar types can also use alias type names such as `int16` instead 220 of `short` and `float32` instead of `float`. Thus we could also write 221 the `Weapon` table as: 222 223 table Weapon { 224 name:string; 225 damage:int16; 226 } 227 228 #### More Information About Schemas 229 230 You can find a complete guide to writing `schema` files in the 231 [Writing a schema](@ref flatbuffers_guide_writing_schema) section of the 232 Programmer's Guide. You can also view the formal 233 [Grammar of the schema language](@ref flatbuffers_grammar). 234 235 ## Compiling the Monsters' Schema 236 237 After you have written the FlatBuffers schema, the next step is to compile it. 238 239 If you have not already done so, please follow 240 [these instructions](@ref flatbuffers_guide_building) to build `flatc`, the 241 FlatBuffer compiler. 242 243 Once `flatc` is built successfully, compile the schema for your language: 244 245 <div class="language-c"> 246 *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.* 247 <br> 248 See [flatcc build instructions](https://github.com/dvidelabs/flatcc#building). 249 <br> 250 Please be aware of the difference between `flatc` and `flatcc` tools. 251 <br> 252 </div> 253 254 <div class="language-cpp"> 255 ~~~{.sh} 256 cd flatbuffers/sample 257 ./../flatc --cpp samples/monster.fbs 258 ~~~ 259 </div> 260 <div class="language-java"> 261 ~~~{.sh} 262 cd flatbuffers/sample 263 ./../flatc --java samples/monster.fbs 264 ~~~ 265 </div> 266 <div class="language-csharp"> 267 ~~~{.sh} 268 cd flatbuffers/sample 269 ./../flatc --csharp samples/monster.fbs 270 ~~~ 271 </div> 272 <div class="language-go"> 273 ~~~{.sh} 274 cd flatbuffers/sample 275 ./../flatc --go samples/monster.fbs 276 ~~~ 277 </div> 278 <div class="language-python"> 279 ~~~{.sh} 280 cd flatbuffers/sample 281 ./../flatc --python samples/monster.fbs 282 ~~~ 283 </div> 284 <div class="language-javascript"> 285 ~~~{.sh} 286 cd flatbuffers/sample 287 ./../flatc --javascript samples/monster.fbs 288 ~~~ 289 </div> 290 <div class="language-php"> 291 ~~~{.sh} 292 cd flatbuffers/sample 293 ./../flatc --php samples/monster.fbs 294 ~~~ 295 </div> 296 <div class="language-c"> 297 ~~~{.sh} 298 cd flatcc 299 mkdir -p build/tmp/samples/monster 300 bin/flatcc -a -o build/tmp/samples/monster samples/monster/monster.fbs 301 # or just 302 flatcc/samples/monster/build.sh 303 ~~~ 304 </div> 305 306 For a more complete guide to using the `flatc` compiler, please read the 307 [Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) 308 section of the Programmer's Guide. 309 310 ## Reading and Writing Monster FlatBuffers 311 312 Now that we have compiled the schema for our programming language, we can 313 start creating some monsters and serializing/deserializing them from 314 FlatBuffers. 315 316 #### Creating and Writing Orc FlatBuffers 317 318 The first step is to import/include the library, generated files, etc. 319 320 <div class="language-cpp"> 321 ~~~{.cpp} 322 #include "monster_generate.h" // This was generated by `flatc`. 323 324 using namespace MyGame::Sample; // Specified in the schema. 325 ~~~ 326 </div> 327 <div class="language-java"> 328 ~~~{.java} 329 import MyGame.Sample.*; //The `flatc` generated files. (Monster, Vec3, etc.) 330 331 import com.google.flatbuffers.FlatBufferBuilder; 332 ~~~ 333 </div> 334 <div class="language-csharp"> 335 ~~~{.cs} 336 using FlatBuffers; 337 using MyGame.Sample; // The `flatc` generated files. (Monster, Vec3, etc.) 338 ~~~ 339 </div> 340 <div class="language-go"> 341 ~~~{.go} 342 import ( 343 flatbuffers "github.com/google/flatbuffers/go" 344 sample "MyGame/Sample" 345 ) 346 ~~~ 347 </div> 348 <div class="language-python"> 349 ~~~{.py} 350 import flatbuffers 351 352 # Generated by `flatc`. 353 import MyGame.Sample.Color 354 import MyGame.Sample.Equipment 355 import MyGame.Sample.Monster 356 import MyGame.Sample.Vec3 357 import MyGame.Sample.Weapon 358 ~~~ 359 </div> 360 <div class="language-javascript"> 361 ~~~{.js} 362 // The following code is for JavaScript module loaders (e.g. Node.js). See 363 // below for a browser-based HTML/JavaScript example of including the library. 364 var flatbuffers = require('/js/flatbuffers').flatbuffers; 365 var MyGame = require('./monster_generated').MyGame; // Generated by `flatc`. 366 367 //--------------------------------------------------------------------------// 368 369 // The following code is for browser-based HTML/JavaScript. Use the above code 370 // for JavaScript module loaders (e.g. Node.js). 371 <script src="../js/flatbuffers.js"></script> 372 <script src="monster_generated.js"></script> // Generated by `flatc`. 373 ~~~ 374 </div> 375 <div class="language-php"> 376 ~~~{.php} 377 // It is recommended that your use PSR autoload when using FlatBuffers in PHP. 378 // Here is an example from `SampleBinary.php`: 379 function __autoload($class_name) { 380 // The last segment of the class name matches the file name. 381 $class = substr($class_name, strrpos($class_name, "\\") + 1); 382 $root_dir = join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)))); // `flatbuffers` root. 383 384 // Contains the `*.php` files for the FlatBuffers library and the `flatc` generated files. 385 $paths = array(join(DIRECTORY_SEPARATOR, array($root_dir, "php")), 386 join(DIRECTORY_SEPARATOR, array($root_dir, "samples", "MyGame", "Sample"))); 387 foreach ($paths as $path) { 388 $file = join(DIRECTORY_SEPARATOR, array($path, $class . ".php")); 389 if (file_exists($file)) { 390 require($file); 391 break; 392 } 393 } 394 } 395 ~~~ 396 </div> 397 <div class="language-c"> 398 ~~~{.c} 399 #include "monster_builder.h" // Generated by `flatcc`. 400 401 // Convenient namespace macro to manage long namespace prefix. 402 #undef ns 403 #define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) // Specified in the schema. 404 405 // A helper to simplify creating vectors from C-arrays. 406 #define c_vec_len(V) (sizeof(V)/sizeof((V)[0])) 407 ~~~ 408 </div> 409 410 Now we are ready to start building some buffers. In order to start, we need 411 to create an instance of the `FlatBufferBuilder`, which will contain the buffer 412 as it grows. You can pass an initial size of the buffer (here 1024 bytes), 413 which will grow automatically if needed: 414 415 <div class="language-cpp"> 416 ~~~{.cpp} 417 // Create a `FlatBufferBuilder`, which will be used to create our 418 // monsters' FlatBuffers. 419 flatbuffers::FlatBufferBuilder builder(1024); 420 ~~~ 421 </div> 422 <div class="language-java"> 423 ~~~{.java} 424 // Create a `FlatBufferBuilder`, which will be used to create our 425 // monsters' FlatBuffers. 426 FlatBufferBuilder builder = new FlatBufferBuilder(1024); 427 ~~~ 428 </div> 429 <div class="language-csharp"> 430 ~~~{.cs} 431 // Create a `FlatBufferBuilder`, which will be used to create our 432 // monsters' FlatBuffers. 433 var builder = new FlatBufferBuilder(1024); 434 ~~~ 435 </div> 436 <div class="language-go"> 437 ~~~{.go} 438 // Create a `FlatBufferBuilder`, which will be used to create our 439 // monsters' FlatBuffers. 440 builder := flatbuffers.NewBuilder(1024) 441 ~~~ 442 </div> 443 <div class="language-python"> 444 ~~~{.py} 445 # Create a `FlatBufferBuilder`, which will be used to create our 446 # monsters' FlatBuffers. 447 builder = flatbuffers.Builder(1024) 448 ~~~ 449 </div> 450 <div class="language-javascript"> 451 ~~~{.js} 452 // Create a `flatbuffer.Builder`, which will be used to create our 453 // monsters' FlatBuffers. 454 var builder = new flatbuffers.Builder(1024); 455 ~~~ 456 </div> 457 <div class="language-php"> 458 ~~~{.php} 459 // Create a `FlatBufferBuilder`, which will be used to create our 460 // monsters' FlatBuffers. 461 $builder = new Google\FlatBuffers\FlatbufferBuilder(1024); 462 ~~~ 463 </div> 464 <div class="language-c"> 465 ~~~{.c} 466 flatcc_builder_t builder, *B; 467 B = &builder; 468 // Initialize the builder object. 469 flatcc_builder_init(B); 470 ~~~ 471 </div> 472 473 After creating the `builder`, we can start serializing our data. Before we make 474 our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`. 475 476 <div class="language-cpp"> 477 ~~~{.cpp} 478 auto weapon_one_name = builder.CreateString("Sword"); 479 short weapon_one_damage = 3; 480 481 auto weapon_two_name = builder.CreateString("Axe"); 482 short weapon_two_damage = 5; 483 484 // Use the `CreateWeapon` shortcut to create Weapons with all the fields set. 485 auto sword = CreateWeapon(builder, weapon_one_name, weapon_one_damage); 486 auto axe = CreateWeapon(builder, weapon_two_name, weapon_two_damage); 487 ~~~ 488 </div> 489 <div class="language-java"> 490 ~~~{.java} 491 int weaponOneName = builder.createString("Sword") 492 short weaponOneDamage = 3; 493 494 int weaponTwoName = builder.createString("Axe"); 495 short weaponTwoDamage = 5; 496 497 // Use the `createWeapon()` helper function to create the weapons, since we set every field. 498 int sword = Weapon.createWeapon(builder, weaponOneName, weaponOneDamage); 499 int axe = Weapon.createWeapon(builder, weaponTwoName, weaponTwoDamage); 500 ~~~ 501 </div> 502 <div class="language-csharp"> 503 ~~~{.cs} 504 var weaponOneName = builder.CreateString("Sword"); 505 var weaponOneDamage = 3; 506 507 var weaponTwoName = builder.CreateString("Axe"); 508 var weaponTwoDamage = 5; 509 510 // Use the `CreateWeapon()` helper function to create the weapons, since we set every field. 511 var sword = Weapon.CreateWeapon(builder, weaponOneName, (short)weaponOneDamage); 512 var axe = Weapon.CreateWeapon(builder, weaponTwoName, (short)weaponTwoDamage); 513 ~~~ 514 </div> 515 <div class="language-go"> 516 ~~~{.go} 517 weaponOne := builder.CreateString("Sword") 518 weaponTwo := builder.CreateString("Axe") 519 520 // Create the first `Weapon` ("Sword"). 521 sample.WeaponStart(builder) 522 sample.Weapon.AddName(builder, weaponOne) 523 sample.Weapon.AddDamage(builder, 3) 524 sword := sample.WeaponEnd(builder) 525 526 // Create the second `Weapon` ("Axe"). 527 sample.WeaponStart(builder) 528 sample.Weapon.AddName(builder, weaponTwo) 529 sample.Weapon.AddDamage(builder, 5) 530 axe := sample.WeaponEnd(builder) 531 ~~~ 532 </div> 533 <div class="language-python"> 534 ~~~{.py} 535 weapon_one = builder.CreateString('Sword') 536 weapon_two = builder.CreateString('Axe') 537 538 # Create the first `Weapon` ('Sword'). 539 MyGame.Sample.Weapon.WeaponStart(builder) 540 MyGame.Sample.Weapon.WeaponAddName(builder, weapon_one) 541 MyGame.Sample.Weapon.WeaponAddDamage(builder, 3) 542 sword = MyGame.Sample.Weapon.WeaponEnd(builder) 543 544 # Create the second `Weapon` ('Axe'). 545 MyGame.Sample.Weapon.WeaponStart(builder) 546 MyGame.Sample.Weapon.WeaponAddName(builder, weapon_two) 547 MyGame.Sample.Weapon.WeaponAddDamage(builder, 5) 548 axe = MyGame.Sample.Weapon.WeaponEnd(builder) 549 ~~~ 550 </div> 551 <div class="language-javascript"> 552 ~~~{.js} 553 var weaponOne = builder.createString('Sword'); 554 var weaponTwo = builder.createString('Axe'); 555 556 // Create the first `Weapon` ('Sword'). 557 MyGame.Sample.Weapon.startWeapon(builder); 558 MyGame.Sample.Weapon.addName(builder, weaponOne); 559 MyGame.Sample.Weapon.addDamage(builder, 3); 560 var sword = MyGame.Sample.Weapon.endWeapon(builder); 561 562 // Create the second `Weapon` ('Axe'). 563 MyGame.Sample.Weapon.startWeapon(builder); 564 MyGame.Sample.Weapon.addName(builder, weaponTwo); 565 MyGame.Sample.Weapon.addDamage(builder, 5); 566 var axe = MyGame.Sample.Weapon.endWeapon(builder); 567 ~~~ 568 </div> 569 <div class="language-php"> 570 ~~~{.php} 571 // Create the `Weapon`s using the `createWeapon()` helper function. 572 $weapon_one_name = $builder->createString("Sword"); 573 $sword = \MyGame\Sample\Weapon::CreateWeapon($builder, $weapon_one_name, 3); 574 575 $weapon_two_name = $builder->createString("Axe"); 576 $axe = \MyGame\Sample\Weapon::CreateWeapon($builder, $weapon_two_name, 5); 577 578 // Create an array from the two `Weapon`s and pass it to the 579 // `CreateWeaponsVector()` method to create a FlatBuffer vector. 580 $weaps = array($sword, $axe); 581 $weapons = \MyGame\Sample\Monster::CreateWeaponsVector($builder, $weaps); 582 ~~~ 583 </div> 584 <div class="language-c"> 585 ~~~{.c} 586 ns(Weapon_ref_t) weapon_one_name = flatbuffers_string_create_str(B, "Sword"); 587 uint16_t weapon_one_damage = 3; 588 589 ns(Weapon_ref_t) weapon_two_name = flatbuffers_string_create_str(B, "Axe"); 590 uint16_t weapon_two_damage = 5; 591 592 ns(Weapon_ref_t) sword = ns(Weapon_create(B, weapon_one_name, weapon_one_damage)); 593 ns(Weapon_ref_t) axe = ns(Weapon_create(B, weapon_two_name, weapon_two_damage)); 594 ~~~ 595 </div> 596 597 Now let's create our monster, the `orc`. For this `orc`, lets make him 598 `red` with rage, positioned at `(1.0, 2.0, 3.0)`, and give him 599 a large pool of hit points with `300`. We can give him a vector of weapons 600 to choose from (our `Sword` and `Axe` from earlier). In this case, we will 601 equip him with the `Axe`, since it is the most powerful of the two. Lastly, 602 let's fill his inventory with some potential treasures that can be taken once he 603 is defeated. 604 605 Before we serialize a monster, we need to first serialize any objects that are 606 contained there-in, i.e. we serialize the data tree using depth-first, pre-order 607 traversal. This is generally easy to do on any tree structures. 608 609 <div class="language-cpp"> 610 ~~~{.cpp} 611 // Serialize a name for our monster, called "Orc". 612 auto name = builder.CreateString("Orc"); 613 614 // Create a `vector` representing the inventory of the Orc. Each number 615 // could correspond to an item that can be claimed after he is slain. 616 unsigned char treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 617 auto inventory = builder.CreateVector(treasure, 10); 618 ~~~ 619 </div> 620 <div class="language-java"> 621 ~~~{.java} 622 // Serialize a name for our monster, called "Orc". 623 int name = builder.createString("Orc"); 624 625 // Create a `vector` representing the inventory of the Orc. Each number 626 // could correspond to an item that can be claimed after he is slain. 627 byte[] treasure = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 628 int inv = Monster.createInventoryVector(builder, treasure); 629 ~~~ 630 </div> 631 <div class="language-csharp"> 632 ~~~{.cs} 633 // Serialize a name for our monster, called "Orc". 634 var name = builder.CreateString("Orc"); 635 636 // Create a `vector` representing the inventory of the Orc. Each number 637 // could correspond to an item that can be claimed after he is slain. 638 // Note: Since we prepend the bytes, this loop iterates in reverse order. 639 Monster.StartInventoryVector(builder, 10); 640 for (int i = 9; i >= 0; i--) 641 { 642 builder.AddByte((byte)i); 643 } 644 var inv = builder.EndVector(); 645 ~~~ 646 </div> 647 <div class="language-go"> 648 ~~~{.go} 649 // Serialize a name for our monster, called "Orc". 650 name := builder.CreateString("Orc") 651 652 // Create a `vector` representing the inventory of the Orc. Each number 653 // could correspond to an item that can be claimed after he is slain. 654 // Note: Since we prepend the bytes, this loop iterates in reverse. 655 sample.MonsterStartInventoryVector(builder, 10) 656 for i := 9; i >= 0; i-- { 657 builder.PrependByte(byte(i)) 658 } 659 int := builder.EndVector(10) 660 ~~~ 661 </div> 662 <div class="language-python"> 663 ~~~{.py} 664 # Serialize a name for our monster, called "Orc". 665 name = builder.CreateString("Orc") 666 667 # Create a `vector` representing the inventory of the Orc. Each number 668 # could correspond to an item that can be claimed after he is slain. 669 # Note: Since we prepend the bytes, this loop iterates in reverse. 670 MyGame.Sample.Monster.MonsterStartInventoryVector(builder, 10) 671 for i in reversed(range(0, 10)): 672 builder.PrependByte(i) 673 inv = builder.EndVector(10) 674 ~~~ 675 </div> 676 <div class="language-javascript"> 677 ~~~{.js} 678 // Serialize a name for our monster, called 'Orc'. 679 var name = builder.createString('Orc'); 680 681 // Create a `vector` representing the inventory of the Orc. Each number 682 // could correspond to an item that can be claimed after he is slain. 683 var treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 684 var inv = MyGame.Sample.Monster.createInventoryVector(builder, treasure); 685 ~~~ 686 </div> 687 <div class="language-php"> 688 ~~~{.php} 689 // Serialize a name for our monster, called "Orc". 690 $name = $builder->createString("Orc"); 691 692 // Create a `vector` representing the inventory of the Orc. Each number 693 // could correspond to an item that can be claimed after he is slain. 694 $treasure = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); 695 $inv = \MyGame\Sample\Monster::CreateInventoryVector($builder, $treasure); 696 ~~~ 697 </div> 698 <div class="language-c"> 699 ~~~{.c} 700 // Serialize a name for our monster, called "Orc". 701 // The _str suffix indicates the source is an ascii-z string. 702 flatbuffers_string_ref_t name = flatbuffers_string_create_str(B, "Orc"); 703 704 // Create a `vector` representing the inventory of the Orc. Each number 705 // could correspond to an item that can be claimed after he is slain. 706 uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 707 flatbuffers_uint8_vec_ref_t inventory; 708 // `c_vec_len` is the convenience macro we defined earlier. 709 inventory = flatbuffers_uint8_vec_create(B, treasure, c_vec_len(treasure)); 710 ~~~ 711 </div> 712 713 We serialized two built-in data types (`string` and `vector`) and captured 714 their return values. These values are offsets into the serialized data, 715 indicating where they are stored, such that we can refer to them below when 716 adding fields to our monster. 717 718 *Note: To create a `vector` of nested objects (e.g. `table`s, `string`s, or 719 other `vector`s), collect their offsets into a temporary data structure, and 720 then create an additional `vector` containing their offsets.* 721 722 If instead of creating a vector from an existing array you serialize elements 723 individually one by one, take care to note that this happens in reverse order, 724 as buffers are built back to front. 725 726 For example, take a look at the two `Weapon`s that we created earlier (`Sword` 727 and `Axe`). These are both FlatBuffer `table`s, whose offsets we now store in 728 memory. Therefore we can create a FlatBuffer `vector` to contain these 729 offsets. 730 731 <div class="language-cpp"> 732 ~~~{.cpp} 733 // Place the weapons into a `std::vector`, then convert that into a FlatBuffer `vector`. 734 std::vector<flatbuffers::Offset<Weapon>> weapons_vector; 735 weapons_vector.push_back(sword); 736 weapons_vector.push_back(axe); 737 auto weapons = builder.CreateVector(weapons_vector); 738 ~~~ 739 </div> 740 <div class="language-java"> 741 ~~~{.java} 742 // Place the two weapons into an array, and pass it to the `createWeaponsVector()` method to 743 // create a FlatBuffer vector. 744 int[] weaps = new int[2]; 745 weaps[0] = sword; 746 weaps[1] = axe; 747 748 // Pass the `weaps` array into the `createWeaponsVector()` method to create a FlatBuffer vector. 749 int weapons = Monster.createWeaponsVector(builder, weaps); 750 ~~~ 751 </div> 752 <div class="language-csharp"> 753 ~~~{.cs} 754 var weaps = new Offset<Weapon>[2]; 755 weaps[0] = sword; 756 weaps[1] = axe; 757 758 // Pass the `weaps` array into the `CreateWeaponsVector()` method to create a FlatBuffer vector. 759 var weapons = Monster.CreateWeaponsVector(builder, weaps); 760 ~~~ 761 </div> 762 <div class="language-go"> 763 ~~~{.go} 764 // Create a FlatBuffer vector and prepend the weapons. 765 // Note: Since we prepend the data, prepend them in reverse order. 766 sample.MonsterStartWeaponsVector(builder, 2) 767 builder.PrependUOffsetT(axe) 768 builder.PrependUOffsetT(sword) 769 weapons := builder.EndVector(2) 770 ~~~ 771 </div> 772 <div class="language-python"> 773 ~~~{.py} 774 # Create a FlatBuffer vector and prepend the weapons. 775 # Note: Since we prepend the data, prepend them in reverse order. 776 MyGame.Sample.Monster.MonsterStartWeaponsVector(builder, 2) 777 builder.PrependUOffsetTRelative(axe) 778 builder.PrependUOffsetTRelative(sword) 779 weapons = builder.EndVector(2) 780 ~~~ 781 </div> 782 <div class="language-javascript"> 783 ~~~{.js} 784 // Create an array from the two `Weapon`s and pass it to the 785 // `createWeaponsVector()` method to create a FlatBuffer vector. 786 var weaps = [sword, axe]; 787 var weapons = MyGame.Sample.Monster.createWeaponsVector(builder, weaps); 788 ~~~ 789 </div> 790 <div class="language-php"> 791 ~~~{.php} 792 // Create an array from the two `Weapon`s and pass it to the 793 // `CreateWeaponsVector()` method to create a FlatBuffer vector. 794 $weaps = array($sword, $axe); 795 $weapons = \MyGame\Sample\Monster::CreateWeaponsVector($builder, $weaps); 796 ~~~ 797 </div> 798 <div class="language-c"> 799 ~~~{.c} 800 // We use the internal builder stack to implement a dynamic vector. 801 ns(Weapon_vec_start(B)); 802 ns(Weapon_vec_push(B, sword)); 803 ns(Weapon_vec_push(B, axe)); 804 ns(Weapon_vec_ref_t) weapons = ns(Weapon_vec_end(B)); 805 ~~~ 806 </div> 807 808 <div class="language-cpp"> 809 <br> 810 Note there's additional convenience overloads of `CreateVector`, allowing you 811 to work with data that's not in a `std::vector`, or allowing you to generate 812 elements by calling a lambda. For the common case of `std::vector<std::string>` 813 there's also `CreateVectorOfStrings`. 814 </div> 815 816 Note that vectors of structs are serialized differently from tables, since 817 structs are stored in-line in the vector. For example, to create a vector 818 for the `path` field above: 819 820 <div class="language-cpp"> 821 ~~~{.cpp} 822 Vec3 points[] = { Vec3(1.0f, 2.0f, 3.0f), Vec3(4.0f, 5.0f, 6.0f) }; 823 auto path = builder.CreateVectorOfStructs(points, 2); 824 ~~~ 825 </div> 826 <div class="language-java"> 827 ~~~{.java} 828 Monster.startPathVector(fbb, 2); 829 Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f); 830 Vec3.createVec3(builder, 4.0f, 5.0f, 6.0f); 831 int path = fbb.endVector(); 832 ~~~ 833 </div> 834 <div class="language-csharp"> 835 ~~~{.cs} 836 Monster.StartPathVector(fbb, 2); 837 Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f); 838 Vec3.CreateVec3(builder, 4.0f, 5.0f, 6.0f); 839 var path = fbb.EndVector(); 840 ~~~ 841 </div> 842 <div class="language-go"> 843 ~~~{.go} 844 sample.MonsterStartPathVector(builder, 2) 845 sample.CreateVec3(builder, 1.0, 2.0, 3.0) 846 sample.CreateVec3(builder, 4.0, 5.0, 6.0) 847 path := builder.EndVector(2) 848 ~~~ 849 </div> 850 <div class="language-python"> 851 ~~~{.py} 852 MyGame.Sample.Monster.MonsterStartPathVector(builder, 2) 853 MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0) 854 MyGame.Sample.Vec3.CreateVec3(builder, 4.0, 5.0, 6.0) 855 path = builder.EndVector(2) 856 ~~~ 857 </div> 858 <div class="language-javascript"> 859 ~~~{.js} 860 MyGame.Sample.Monster.startPathVector(builder, 2); 861 MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0); 862 MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0); 863 var path = builder.endVector(); 864 ~~~ 865 </div> 866 <div class="language-php"> 867 ~~~{.php} 868 \MyGame\Example\Monster::StartPathVector($builder, 2); 869 \MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0); 870 \MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0); 871 $path = $builder->endVector(); 872 ~~~ 873 </div> 874 <div class="language-c"> 875 ~~~{.c} 876 // TBD 877 ~~~ 878 </div> 879 880 We have now serialized the non-scalar components of the orc, so we 881 can serialize the monster itself: 882 883 <div class="language-cpp"> 884 ~~~{.cpp} 885 // Set his hit points to 300 and his mana to 150. 886 int hp = 300; 887 int mana = 150; 888 889 // Finally, create the monster using the `CreateMonster` helper function 890 // to set all fields. 891 auto orc = CreateMonster(builder, Vec3(1.0f, 2.0f, 3.0f), mana, hp, name, 892 inventory, Color_Red, weapons, Equipment_Weapon, 893 axe.Union(), path); 894 ~~~ 895 </div> 896 <div class="language-java"> 897 ~~~{.java} 898 // Create our monster using `startMonster()` and `endMonster()`. 899 Monster.startMonster(builder); 900 Monster.addPos(builder, Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f)); 901 Monster.addName(builder, name); 902 Monster.addColor(builder, Color.Red); 903 Monster.addHp(builder, (short)300); 904 Monster.addInventory(builder, inv); 905 Monster.addWeapons(builder, weapons); 906 Monster.addEquippedType(builder, Equipment.Weapon); 907 Monster.addEquipped(builder, axe); 908 Monster.addPath(builder, path); 909 int orc = Monster.endMonster(builder); 910 ~~~ 911 </div> 912 <div class="language-csharp"> 913 ~~~{.cs} 914 // Create our monster using `StartMonster()` and `EndMonster()`. 915 Monster.StartMonster(builder); 916 Monster.AddPos(builder, Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f)); 917 Monster.AddHp(builder, (short)300); 918 Monster.AddName(builder, name); 919 Monster.AddInventory(builder, inv); 920 Monster.AddColor(builder, Color.Red); 921 Monster.AddWeapons(builder, weapons); 922 Monster.AddEquippedType(builder, Equipment.Weapon); 923 Monster.AddEquipped(builder, axe.Value); // Axe 924 Monster.AddPath(builder, path); 925 var orc = Monster.EndMonster(builder); 926 ~~~ 927 </div> 928 <div class="language-go"> 929 ~~~{.go} 930 // Create our monster using `MonsterStart()` and `MonsterEnd()`. 931 sample.MonsterStart(builder) 932 sample.MonsterAddPos(builder, sample.CreateVec3(builder, 1.0, 2.0, 3.0)) 933 sample.MonsterAddHp(builder, 300) 934 sample.MonsterAddName(builder, name) 935 sample.MonsterAddInventory(builder, inv) 936 sample.MonsterAddColor(builder, sample.ColorRed) 937 sample.MonsterAddWeapons(builder, weapons) 938 sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon) 939 sample.MonsterAddEquipped(builder, axe) 940 sample.MonsterAddPath(builder, path) 941 orc := sample.MonsterEnd(builder) 942 ~~~ 943 </div> 944 <div class="language-python"> 945 ~~~{.py} 946 # Create our monster by using `MonsterStart()` and `MonsterEnd()`. 947 MyGame.Sample.Monster.MonsterStart(builder) 948 MyGame.Sample.Monster.MonsterAddPos(builder, 949 MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0)) 950 MyGame.Sample.Monster.MonsterAddHp(builder, 300) 951 MyGame.Sample.Monster.MonsterAddName(builder, name) 952 MyGame.Sample.Monster.MonsterAddInventory(builder, inv) 953 MyGame.Sample.Monster.MonsterAddColor(builder, 954 MyGame.Sample.Color.Color().Red) 955 MyGame.Sample.Monster.MonsterAddWeapons(builder, weapons) 956 MyGame.Sample.Monster.MonsterAddEquippedType( 957 builder, MyGame.Sample.Equipment.Equipment().Weapon) 958 MyGame.Sample.Monster.MonsterAddEquipped(builder, axe) 959 MyGame.Sample.Monster.MonsterAddPath(builder, path) 960 orc = MyGame.Sample.Monster.MonsterEnd(builder) 961 ~~~ 962 </div> 963 <div class="language-javascript"> 964 ~~~{.js} 965 // Create our monster by using `startMonster()` and `endMonster()`. 966 MyGame.Sample.Monster.startMonster(builder); 967 MyGame.Sample.Monster.addPos(builder, 968 MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0)); 969 MyGame.Sample.Monster.addHp(builder, 300); 970 MyGame.Sample.Monster.addColor(builder, MyGame.Sample.Color.Red) 971 MyGame.Sample.Monster.addName(builder, name); 972 MyGame.Sample.Monster.addInventory(builder, inv); 973 MyGame.Sample.Monster.addWeapons(builder, weapons); 974 MyGame.Sample.Monster.addEquippedType(builder, MyGame.Sample.Equipment.Weapon); 975 MyGame.Sample.Monster.addEquipped(builder, axe); 976 MyGame.Sample.Monster.addPath(builder, path); 977 var orc = MyGame.Sample.Monster.endMonster(builder); 978 ~~~ 979 </div> 980 <div class="language-php"> 981 ~~~{.php} 982 // Create our monster by using `StartMonster()` and `EndMonster()`. 983 \MyGame\Sample\Monster::StartMonster($builder); 984 \MyGame\Sample\Monster::AddPos($builder, 985 \MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0)); 986 \MyGame\Sample\Monster::AddHp($builder, 300); 987 \MyGame\Sample\Monster::AddName($builder, $name); 988 \MyGame\Sample\Monster::AddInventory($builder, $inv); 989 \MyGame\Sample\Monster::AddColor($builder, \MyGame\Sample\Color::Red); 990 \MyGame\Sample\Monster::AddWeapons($builder, $weapons); 991 \MyGame\Sample\Monster::AddEquippedType($builder, \MyGame\Sample\Equipment::Weapon); 992 \MyGame\Sample\Monster::AddEquipped($builder, $axe); 993 \MyGame\Sample\Monster::AddPath($builder, $path); 994 $orc = \MyGame\Sample\Monster::EndMonster($builder); 995 ~~~ 996 </div> 997 <div class="language-c"> 998 ~~~{.c} 999 // Set his hit points to 300 and his mana to 150. 1000 uint16_t hp = 300; 1001 uint16_t mana = 150; 1002 1003 // Define an equipment union. `create` calls in C has a single 1004 // argument for unions where C++ has both a type and a data argument. 1005 ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe)); 1006 ns(Vec3_t) pos = { 1.0f, 2.0f, 3.0f }; 1007 ns(Monster_create_as_root(B, &pos, mana, hp, name, inventory, ns(Color_Red), 1008 weapons, equipped, path)); 1009 ~~~ 1010 </div> 1011 1012 Note how we create `Vec3` struct in-line in the table. Unlike tables, structs 1013 are simple combinations of scalars that are always stored inline, just like 1014 scalars themselves. 1015 1016 **Important**: Unlike structs, you should not nest tables or other objects, 1017 which is why we created all the strings/vectors/tables that this monster refers 1018 to before `start`. If you try to create any of them between `start` and `end`, 1019 you will get an assert/exception/panic depending on your language. 1020 1021 *Note: Since we are passing `150` as the `mana` field, which happens to be the 1022 default value, the field will not actually be written to the buffer, since the 1023 default value will be returned on query anyway. This is a nice space savings, 1024 especially if default values are common in your data. It also means that you do 1025 not need to be worried of adding a lot of fields that are only used in a small 1026 number of instances, as it will not bloat the buffer if unused.* 1027 1028 <div class="language-cpp"> 1029 <br> 1030 If you do not wish to set every field in a `table`, it may be more convenient to 1031 manually set each field of your monster, instead of calling `CreateMonster()`. 1032 The following snippet is functionally equivalent to the above code, but provides 1033 a bit more flexibility. 1034 <br> 1035 ~~~{.cpp} 1036 // You can use this code instead of `CreateMonster()`, to create our orc 1037 // manually. 1038 MonsterBuilder monster_builder(builder); 1039 monster_builder.add_pos(&pos); 1040 auto pos = Vec3(1.0f, 2.0f, 3.0f); 1041 monster_builder.add_hp(hp); 1042 monster_builder.add_name(name); 1043 monster_builder.add_inventory(inventory); 1044 monster_builder.add_color(Color_Red); 1045 monster_builder.add_weapons(weapons); 1046 monster_builder.add_equipped_type(Equipment_Weapon); 1047 monster_builder.add_equpped(axe.Union()); 1048 auto orc = monster_builder.Finish(); 1049 ~~~ 1050 </div> 1051 <div class="language-c"> 1052 If you do not wish to set every field in a `table`, it may be more convenient to 1053 manually set each field of your monster, instead of calling `create_monster_as_root()`. 1054 The following snippet is functionally equivalent to the above code, but provides 1055 a bit more flexibility. 1056 <br> 1057 ~~~{.c} 1058 // It is important to pair `start_as_root` with `end_as_root`. 1059 ns(Monster_start_as_root(B)); 1060 ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f)); 1061 // or alternatively 1062 //ns(Monster_pos_add(&pos); 1063 1064 ns(Monster_hp_add(B, hp)); 1065 // Notice that `Monser_name_add` adds a string reference unlike the 1066 // add_str and add_strn variants. 1067 ns(Monster_name_add(B, name)); 1068 ns(Monster_inventory_add(B, inventory)); 1069 ns(Monster_color_add(B, ns(Color_Red))); 1070 ns(Monster_weapons_add(B, weapons)); 1071 ns(Monster_equipped_add(B, equipped)); 1072 // Complete the monster object and make it the buffer root object. 1073 ns(Monster_end_as_root(B)); 1074 ~~~ 1075 </div> 1076 1077 Before finishing the serialization, let's take a quick look at FlatBuffer 1078 `union Equipped`. There are two parts to each FlatBuffer `union`. The first, is 1079 a hidden field `_type`, that is generated to hold the type of `table` referred 1080 to by the `union`. This allows you to know which type to cast to at runtime. 1081 Second, is the `union`'s data. 1082 1083 In our example, the last two things we added to our `Monster` were the 1084 `Equipped Type` and the `Equipped` union itself. 1085 1086 Here is a repetition these lines, to help highlight them more clearly: 1087 1088 <div class="language-cpp"> 1089 ~~~{.cpp} 1090 monster_builder.add_equipped_type(Equipment_Weapon); // Union type 1091 monster_builder.add_equipped(axe); // Union data 1092 ~~~ 1093 </div> 1094 <div class="language-java"> 1095 ~~~{.java} 1096 Monster.addEquippedType(builder, Equipment.Weapon); // Union type 1097 Monster.addEquipped(axe); // Union data 1098 ~~~ 1099 </div> 1100 <div class="language-csharp"> 1101 ~~~{.cs} 1102 Monster.AddEquippedType(builder, Equipment.Weapon); // Union type 1103 Monster.AddEquipped(builder, axe.Value); // Union data 1104 ~~~ 1105 </div> 1106 <div class="language-go"> 1107 ~~~{.go} 1108 sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon) // Union type 1109 sample.MonsterAddEquipped(builder, axe) // Union data 1110 ~~~ 1111 </div> 1112 <div class="language-python"> 1113 ~~~{.py} 1114 MyGame.Sample.Monster.MonsterAddEquippedType( # Union type 1115 builder, MyGame.Sample.Equipment.Equipment().Weapon) 1116 MyGame.Sample.Monster.MonsterAddEquipped(builder, axe) # Union data 1117 ~~~ 1118 </div> 1119 <div class="language-javascript"> 1120 ~~~{.js} 1121 MyGame.Sample.Monster.addEquippedType(builder, MyGame.Sample.Equipment.Weapon); // Union type 1122 MyGame.Sample.Monster.addEquipped(builder, axe); // Union data 1123 ~~~ 1124 </div> 1125 <div class="language-php"> 1126 ~~~{.php} 1127 \MyGame\Sample\Monster::AddEquippedType($builder, \MyGame\Sample\Equipment::Weapon); // Union type 1128 \MyGame\Sample\Monster::AddEquipped($builder, $axe); // Union data 1129 ~~~ 1130 </div> 1131 <div class="language-c"> 1132 ~~~{.c} 1133 // Add union type and data simultanously. 1134 ns(Monster_equipped_Weapon_add(B, axe)); 1135 ~~~ 1136 </div> 1137 1138 After you have created your buffer, you will have the offset to the root of the 1139 data in the `orc` variable, so you can finish the buffer by calling the 1140 appropriate `finish` method. 1141 1142 1143 <div class="language-cpp"> 1144 ~~~{.cpp} 1145 // Call `Finish()` to instruct the builder that this monster is complete. 1146 // Note: Regardless of how you created the `orc`, you still need to call 1147 // `Finish()` on the `FlatBufferBuilder`. 1148 builder.Finish(orc); // You could also call `FinishMonsterBuffer(builder, 1149 // orc);`. 1150 ~~~ 1151 </div> 1152 <div class="language-java"> 1153 ~~~{.java} 1154 // Call `finish()` to instruct the builder that this monster is complete. 1155 builder.finish(orc); // You could also call `Monster.finishMonsterBuffer(builder, orc);`. 1156 ~~~ 1157 </div> 1158 <div class="language-csharp"> 1159 ~~~{.cs} 1160 // Call `Finish()` to instruct the builder that this monster is complete. 1161 builder.Finish(orc.Value); // You could also call `Monster.FinishMonsterBuffer(builder, orc);`. 1162 ~~~ 1163 </div> 1164 <div class="language-go"> 1165 ~~~{.go} 1166 // Call `Finish()` to instruct the builder that this monster is complete. 1167 builder.Finish(orc) 1168 ~~~ 1169 </div> 1170 <div class="language-python"> 1171 ~~~{.py} 1172 # Call `Finish()` to instruct the builder that this monster is complete. 1173 builder.Finish(orc) 1174 ~~~ 1175 </div> 1176 <div class="language-javascript"> 1177 ~~~{.js} 1178 // Call `finish()` to instruct the builder that this monster is complete. 1179 builder.finish(orc); // You could also call `MyGame.Sample.Monster.finishMonsterBuffer(builder, 1180 // orc);`. 1181 ~~~ 1182 </div> 1183 <div class="language-php"> 1184 ~~~{.php} 1185 // Call `finish()` to instruct the builder that this monster is complete. 1186 $builder->finish($orc); // You may also call `\MyGame\Sample\Monster::FinishMonsterBuffer( 1187 // $builder, $orc);`. 1188 ~~~ 1189 </div> 1190 <div class="language-c"> 1191 ~~~{.c} 1192 // Because we used `Monster_create_as_root`, we do not need a `finish` call in C`. 1193 ~~~ 1194 </div> 1195 1196 The buffer is now ready to be stored somewhere, sent over the network, be 1197 compressed, or whatever you'd like to do with it. You can access the buffer 1198 like so: 1199 1200 <div class="language-cpp"> 1201 ~~~{.cpp} 1202 // This must be called after `Finish()`. 1203 uint8_t *buf = builder.GetBufferPointer(); 1204 int size = builder.GetSize(); // Returns the size of the buffer that 1205 // `GetBufferPointer()` points to. 1206 ~~~ 1207 </div> 1208 <div class="language-java"> 1209 ~~~{.java} 1210 // This must be called after `finish()`. 1211 java.nio.ByteBuffer buf = builder.dataBuffer(); 1212 // The data in this ByteBuffer does NOT start at 0, but at buf.position(). 1213 // The number of bytes is buf.remaining(). 1214 1215 // Alternatively this copies the above data out of the ByteBuffer for you: 1216 bytes[] buf = builder.sizedByteArray(); 1217 ~~~ 1218 </div> 1219 <div class="language-csharp"> 1220 ~~~{.cs} 1221 // This must be called after `Finish()`. 1222 var buf = builder.DataBuffer; // Of type `FlatBuffers.ByteBuffer`. 1223 // The data in this ByteBuffer does NOT start at 0, but at buf.Position. 1224 // The end of the data is marked by buf.Length, so the size is 1225 // buf.Length - buf.Position. 1226 1227 // Alternatively this copies the above data out of the ByteBuffer for you: 1228 bytes[] buf = builder.SizedByteArray(); 1229 ~~~ 1230 </div> 1231 <div class="language-go"> 1232 ~~~{.go} 1233 // This must be called after `Finish()`. 1234 buf := builder.FinishedBytes() // Of type `byte[]`. 1235 ~~~ 1236 </div> 1237 <div class="language-python"> 1238 ~~~{.py} 1239 # This must be called after `Finish()`. 1240 buf = builder.Output() // Of type `bytearray`. 1241 ~~~ 1242 </div> 1243 <div class="language-javascript"> 1244 ~~~{.js} 1245 // This must be called after `finish()`. 1246 var buf = builder.asUint8Array(); // Of type `Uint8Array`. 1247 ~~~ 1248 </div> 1249 <div class="language-php"> 1250 ~~~{.php} 1251 // This must be called after `finish()`. 1252 $buf = $builder->dataBuffer(); // Of type `Google\FlatBuffers\ByteBuffer` 1253 // The data in this ByteBuffer does NOT start at 0, but at buf->getPosition(). 1254 // The end of the data is marked by buf->capacity(), so the size is 1255 // buf->capacity() - buf->getPosition(). 1256 ~~~ 1257 </div> 1258 <div class="language-c"> 1259 ~~~{.c} 1260 uint8_t *buf; 1261 size_t size; 1262 1263 // Allocate and extract a readable buffer from internal builder heap. 1264 // The returned buffer must be deallocated using `free`. 1265 // NOTE: Finalizing the buffer does NOT change the builder, it 1266 // just creates a snapshot of the builder content. 1267 buf = flatcc_builder_finalize_buffer(B, &size); 1268 // use buf 1269 free(buf); 1270 1271 // Optionally reset builder to reuse builder without deallocating 1272 // internal stack and heap. 1273 flatcc_builder_reset(B); 1274 // build next buffer. 1275 // ... 1276 1277 // Cleanup. 1278 flatcc_builder_clear(B); 1279 ~~~ 1280 </div> 1281 1282 Now you can write the bytes to a file, send them over the network.. 1283 **Make sure your file mode (or tranfer protocol) is set to BINARY, not text.** 1284 If you transfer a FlatBuffer in text mode, the buffer will be corrupted, 1285 which will lead to hard to find problems when you read the buffer. 1286 1287 #### Reading Orc FlatBuffers 1288 1289 Now that we have successfully created an `Orc` FlatBuffer, the monster data can 1290 be saved, sent over a network, etc. Let's now adventure into the inverse, and 1291 deserialize a FlatBuffer. 1292 1293 This section requires the same import/include, namespace, etc. requirements as 1294 before: 1295 1296 <div class="language-cpp"> 1297 ~~~{.cpp} 1298 #include "monster_generate.h" // This was generated by `flatc`. 1299 1300 using namespace MyGame::Sample; // Specified in the schema. 1301 ~~~ 1302 </div> 1303 <div class="language-java"> 1304 ~~~{.java} 1305 import MyGame.Sample.*; //The `flatc` generated files. (Monster, Vec3, etc.) 1306 1307 import com.google.flatbuffers.FlatBufferBuilder; 1308 ~~~ 1309 </div> 1310 <div class="language-csharp"> 1311 ~~~{.cs} 1312 using FlatBuffers; 1313 using MyGame.Sample; // The `flatc` generated files. (Monster, Vec3, etc.) 1314 ~~~ 1315 </div> 1316 <div class="language-go"> 1317 ~~~{.go} 1318 import ( 1319 flatbuffers "github.com/google/flatbuffers/go" 1320 sample "MyGame/Sample" 1321 ) 1322 ~~~ 1323 </div> 1324 <div class="language-python"> 1325 ~~~{.py} 1326 import flatbuffers 1327 1328 # Generated by `flatc`. 1329 import MyGame.Sample.Any 1330 import MyGame.Sample.Color 1331 import MyGame.Sample.Monster 1332 import MyGame.Sample.Vec3 1333 ~~~ 1334 </div> 1335 <div class="language-javascript"> 1336 ~~~{.js} 1337 // The following code is for JavaScript module loaders (e.g. Node.js). See 1338 // below for a browser-based HTML/JavaScript example of including the library. 1339 var flatbuffers = require('/js/flatbuffers').flatbuffers; 1340 var MyGame = require('./monster_generated').MyGame; // Generated by `flatc`. 1341 1342 //--------------------------------------------------------------------------// 1343 1344 // The following code is for browser-based HTML/JavaScript. Use the above code 1345 // for JavaScript module loaders (e.g. Node.js). 1346 <script src="../js/flatbuffers.js"></script> 1347 <script src="monster_generated.js"></script> // Generated by `flatc`. 1348 ~~~ 1349 </div> 1350 <div class="language-php"> 1351 ~~~{.php} 1352 // It is recommended that your use PSR autoload when using FlatBuffers in PHP. 1353 // Here is an example from `SampleBinary.php`: 1354 function __autoload($class_name) { 1355 // The last segment of the class name matches the file name. 1356 $class = substr($class_name, strrpos($class_name, "\\") + 1); 1357 $root_dir = join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)))); // `flatbuffers` root. 1358 1359 // Contains the `*.php` files for the FlatBuffers library and the `flatc` generated files. 1360 $paths = array(join(DIRECTORY_SEPARATOR, array($root_dir, "php")), 1361 join(DIRECTORY_SEPARATOR, array($root_dir, "samples", "MyGame", "Sample"))); 1362 foreach ($paths as $path) { 1363 $file = join(DIRECTORY_SEPARATOR, array($path, $class . ".php")); 1364 if (file_exists($file)) { 1365 require($file); 1366 break; 1367 } 1368 } 1369 } 1370 ~~~ 1371 </div> 1372 <div class="language-c"> 1373 ~~~{.c} 1374 // Only needed if we don't have `#include "monster_builder.h"`. 1375 #include "monster_reader.h" 1376 1377 #undef ns 1378 #define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) // Specified in the schema. 1379 ~~~ 1380 </div> 1381 1382 Then, assuming you have a buffer of bytes received from disk, 1383 network, etc., you can create start accessing the buffer like so: 1384 1385 **Again, make sure you read the bytes in BINARY mode, otherwise the code below 1386 won't work** 1387 1388 <div class="language-cpp"> 1389 ~~~{.cpp} 1390 uint8_t *buffer_pointer = /* the data you just read */; 1391 1392 // Get a pointer to the root object inside the buffer. 1393 auto monster = GetMonster(buffer_pointer); 1394 1395 // `monster` is of type `Monster *`. 1396 // Note: root object pointers are NOT the same as `buffer_pointer`. 1397 // `GetMonster` is a convenience function that calls `GetRoot<Monster>`, 1398 // the latter is also available for non-root types. 1399 ~~~ 1400 </div> 1401 <div class="language-java"> 1402 ~~~{.java} 1403 byte[] bytes = /* the data you just read */ 1404 java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(bytes); 1405 1406 // Get an accessor to the root object inside the buffer. 1407 Monster monster = Monster.getRootAsMonster(buf); 1408 ~~~ 1409 </div> 1410 <div class="language-csharp"> 1411 ~~~{.cs} 1412 byte[] bytes = /* the data you just read */ 1413 var buf = new ByteBuffer(bytes); 1414 1415 // Get an accessor to the root object inside the buffer. 1416 var monster = Monster.GetRootAsMonster(buf); 1417 ~~~ 1418 </div> 1419 <div class="language-go"> 1420 ~~~{.go} 1421 var buf []byte = /* the data you just read */ 1422 1423 // Get an accessor to the root object inside the buffer. 1424 monster := sample.GetRootAsMonster(buf, 0) 1425 1426 // Note: We use `0` for the offset here, which is typical for most buffers 1427 // you would read. If you wanted to read from `builder.Bytes` directly, you 1428 // would need to pass in the offset of `builder.Head()`, as the builder 1429 // constructs the buffer backwards, so may not start at offset 0. 1430 ~~~ 1431 </div> 1432 <div class="language-python"> 1433 ~~~{.py} 1434 buf = /* the data you just read, in an object of type "bytearray" */ 1435 1436 // Get an accessor to the root object inside the buffer. 1437 monster = MyGame.Sample.Monster.Monster.GetRootAsMonster(buf, 0) 1438 1439 # Note: We use `0` for the offset here, which is typical for most buffers 1440 # you would read. If you wanted to read from the `builder.Bytes` directly, 1441 # you would need to pass in the offset of `builder.Head()`, as the builder 1442 # constructs the buffer backwards, so may not start at offset 0. 1443 ~~~ 1444 </div> 1445 <div class="language-javascript"> 1446 ~~~{.js} 1447 var bytes = /* the data you just read, in an object of type "Uint8Array" */ 1448 var buf = new flatbuffers.ByteBuffer(bytes); 1449 1450 // Get an accessor to the root object inside the buffer. 1451 var monster = MyGame.Sample.Monster.getRootAsMonster(buf); 1452 ~~~ 1453 </div> 1454 <div class="language-php"> 1455 ~~~{.php} 1456 $bytes = /* the data you just read, in a string */ 1457 $buf = Google\FlatBuffers\ByteBuffer::wrap($bytes); 1458 1459 // Get an accessor to the root object inside the buffer. 1460 $monster = \MyGame\Sample\Monster::GetRootAsMonster($buf); 1461 ~~~ 1462 </div> 1463 <div class="language-c"> 1464 ~~~{.c} 1465 // Note that we use the `table_t` suffix when reading a table object 1466 // as opposed to the `ref_t` suffix used during the construction of 1467 // the buffer. 1468 ns(Monster_table_t) monster = ns(Monster_as_root(buffer)); 1469 1470 // Note: root object pointers are NOT the same as the `buffer` pointer. 1471 ~~~ 1472 </div> 1473 1474 If you look in the generated files from the schema compiler, you will see it generated 1475 accessors for all non-`deprecated` fields. For example: 1476 1477 <div class="language-cpp"> 1478 ~~~{.cpp} 1479 auto hp = monster->hp(); 1480 auto mana = monster->mana(); 1481 auto name = monster->name()->c_str(); 1482 ~~~ 1483 </div> 1484 <div class="language-java"> 1485 ~~~{.java} 1486 short hp = monster.hp(); 1487 short mana = monster.mana(); 1488 String name = monster.name(); 1489 ~~~ 1490 </div> 1491 <div class="language-csharp"> 1492 ~~~{.cs} 1493 // For C#, unlike other languages support by FlatBuffers, most values (except for 1494 // vectors and unions) are available as propreties instead of asccessor methods. 1495 var hp = monster.Hp 1496 var mana = monster.Mana 1497 var name = monster.Name 1498 ~~~ 1499 </div> 1500 <div class="language-go"> 1501 ~~~{.go} 1502 hp := monster.Hp() 1503 mana := monster.Mana() 1504 name := string(monster.Name()) // Note: `monster.Name()` returns a byte[]. 1505 ~~~ 1506 </div> 1507 <div class="language-python"> 1508 ~~~{.py} 1509 hp = monster.Hp() 1510 mana = monster.Mana() 1511 name = monster.Name() 1512 ~~~ 1513 </div> 1514 <div class="language-javascript"> 1515 ~~~{.js} 1516 var hp = $monster.hp(); 1517 var mana = $monster.mana(); 1518 var name = $monster.name(); 1519 ~~~ 1520 </div> 1521 <div class="language-php"> 1522 ~~~{.php} 1523 $hp = $monster->getHp(); 1524 $mana = $monster->getMana(); 1525 $name = monster->getName(); 1526 ~~~ 1527 </div> 1528 <div class="language-c"> 1529 ~~~{.c} 1530 uint16_t hp = ns(Monster_hp(monster)); 1531 uint16_t mana = ns(Monster_mana(monster)); 1532 flatbuffers_string_t name = ns(Monster_name(monster)); 1533 ~~~ 1534 </div> 1535 1536 These should hold `300`, `150`, and `"Orc"` respectively. 1537 1538 *Note: The default value `150` wasn't stored in `mana`, but we are still able to retrieve it.* 1539 1540 To access sub-objects, in the case of our `pos`, which is a `Vec3`: 1541 1542 <div class="language-cpp"> 1543 ~~~{.cpp} 1544 auto pos = monster->pos(); 1545 auto x = pos->x(); 1546 auto y = pos->y(); 1547 auto z = pos->z(); 1548 ~~~ 1549 </div> 1550 <div class="language-java"> 1551 ~~~{.java} 1552 Vec3 pos = monster.pos(); 1553 float x = pos.x(); 1554 float y = pos.y(); 1555 float z = pos.z(); 1556 ~~~ 1557 </div> 1558 <div class="language-csharp"> 1559 ~~~{.cs} 1560 var pos = monster.Pos.Value; 1561 var x = pos.X; 1562 var y = pos.Y; 1563 var z = pos.Z; 1564 ~~~ 1565 </div> 1566 <div class="language-go"> 1567 ~~~{.go} 1568 pos := monster.Pos(nil) 1569 x := pos.X() 1570 y := pos.Y() 1571 z := pos.Z() 1572 1573 // Note: Whenever you access a new object, like in `Pos()`, a new temporary 1574 // accessor object gets created. If your code is very performance sensitive, 1575 // you can pass in a pointer to an existing `Vec3` instead of `nil`. This 1576 // allows you to reuse it across many calls to reduce the amount of object 1577 // allocation/garbage collection. 1578 ~~~ 1579 </div> 1580 <div class="language-python"> 1581 ~~~{.py} 1582 pos = monster.Pos() 1583 x = pos.X() 1584 y = pos.Y() 1585 z = pos.Z() 1586 ~~~ 1587 </div> 1588 <div class="language-javascript"> 1589 ~~~{.js} 1590 var pos = monster.pos(); 1591 var x = pos.x(); 1592 var y = pos.y(); 1593 var z = pos.z(); 1594 ~~~ 1595 </div> 1596 <div class="language-php"> 1597 ~~~{.php} 1598 $pos = $monster->getPos(); 1599 $x = $pos->getX(); 1600 $y = $pos->getY(); 1601 $z = $pos->getZ(); 1602 ~~~ 1603 </div> 1604 <div class="language-c"> 1605 ~~~{.c} 1606 ns(Vec3_struct_t) pos = ns(Monster_pos(monster)); 1607 float x = ns(Vec3_x(pos)); 1608 float y = ns(Vec3_y(pos)); 1609 float z = ns(Vec3_z(pos)); 1610 ~~~ 1611 </div> 1612 1613 `x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively. 1614 1615 *Note: Had we not set `pos` during serialization, it would be a `NULL`-value.* 1616 1617 Similarly, we can access elements of the inventory `vector` by indexing it. You 1618 can also iterate over the length of the array/vector representing the 1619 FlatBuffers `vector`. 1620 1621 <div class="language-cpp"> 1622 ~~~{.cpp} 1623 auto inv = monster->inventory(); // A pointer to a `flatbuffers::Vector<>`. 1624 auto inv_len = inv->Length(); 1625 auto third_item = inv->Get(2); 1626 ~~~ 1627 </div> 1628 <div class="language-java"> 1629 ~~~{.java} 1630 int invLength = monster.inventoryLength(); 1631 byte thirdItem = monster.inventory(2); 1632 ~~~ 1633 </div> 1634 <div class="language-csharp"> 1635 ~~~{.cs} 1636 int invLength = monster.InventoryLength; 1637 var thirdItem = monster.Inventory(2); 1638 ~~~ 1639 </div> 1640 <div class="language-go"> 1641 ~~~{.go} 1642 invLength := monster.InventoryLength() 1643 thirdItem := monster.Inventory(2) 1644 ~~~ 1645 </div> 1646 <div class="language-python"> 1647 ~~~{.py} 1648 inv_len = monster.InventoryLength() 1649 third_item = monster.Inventory(2) 1650 ~~~ 1651 </div> 1652 <div class="language-javascript"> 1653 ~~~{.js} 1654 var invLength = monster.inventoryLength(); 1655 var thirdItem = monster.inventory(2); 1656 ~~~ 1657 </div> 1658 <div class="language-php"> 1659 ~~~{.php} 1660 $inv_len = $monster->getInventoryLength(); 1661 $third_item = $monster->getInventory(2); 1662 ~~~ 1663 </div> 1664 <div class="language-c"> 1665 ~~~{.c} 1666 // If `inv` hasn't been set, it will be null. It is valid get 1667 // the length of null which will be 0, useful for iteration. 1668 flatbuffers_uint8_vec_t inv = ns(Monster_inventory(monster)); 1669 size_t inv_len = flatbuffers_uint8_vec_len(inv); 1670 ~~~ 1671 </div> 1672 1673 For `vector`s of `table`s, you can access the elements like any other vector, 1674 except your need to handle the result as a FlatBuffer `table`: 1675 1676 <div class="language-cpp"> 1677 ~~~{.cpp} 1678 auto weapons = monster->weapons(); // A pointer to a `flatbuffers::Vector<>`. 1679 auto weapon_len = weapons->Length(); 1680 auto second_weapon_name = weapons->Get(1)->name()->str(); 1681 auto second_weapon_damage = weapons->Get(1)->damage() 1682 ~~~ 1683 </div> 1684 <div class="language-java"> 1685 ~~~{.java} 1686 int weaponsLength = monster.weaponsLength(); 1687 String secondWeaponName = monster.weapons(1).name(); 1688 short secondWeaponDamage = monster.weapons(1).damage(); 1689 ~~~ 1690 </div> 1691 <div class="language-csharp"> 1692 ~~~{.cs} 1693 int weaponsLength = monster.WeaponsLength; 1694 var secondWeaponName = monster.Weapons(1).Name; 1695 var secondWeaponDamage = monster.Weapons(1).Damage; 1696 ~~~ 1697 </div> 1698 <div class="language-go"> 1699 ~~~{.go} 1700 weaponLength := monster.WeaponsLength() 1701 weapon := new(sample.Weapon) // We need a `sample.Weapon` to pass into `monster.Weapons()` 1702 // to capture the output of the function. 1703 if monster.Weapons(weapon, 1) { 1704 secondWeaponName := weapon.Name() 1705 secondWeaponDamage := weapon.Damage() 1706 } 1707 ~~~ 1708 </div> 1709 <div class="language-python"> 1710 ~~~{.py} 1711 weapons_length = monster.WeaponsLength() 1712 second_weapon_name = monster.Weapons(1).Name() 1713 second_weapon_damage = monster.Weapons(1).Damage() 1714 ~~~ 1715 </div> 1716 <div class="language-javascript"> 1717 ~~~{.js} 1718 var weaponsLength = monster.weaponsLength(); 1719 var secondWeaponName = monster.weapons(1).name(); 1720 var secondWeaponDamage = monster.weapons(1).damage(); 1721 ~~~ 1722 </div> 1723 <div class="language-php"> 1724 ~~~{.php} 1725 $weapons_len = $monster->getWeaponsLength(); 1726 $second_weapon_name = $monster->getWeapons(1)->getName(); 1727 $second_weapon_damage = $monster->getWeapons(1)->getDamage(); 1728 ~~~ 1729 </div> 1730 <div class="language-c"> 1731 ~~~{.c} 1732 ns(Weapon_vec_t) weapons = ns(Monster_weapons(monster)); 1733 size_t weapons_len = ns(Weapon_vec_len(weapons)); 1734 // We can use `const char *` instead of `flatbuffers_string_t`. 1735 const char *second_weapon_name = ns(Weapon_name(ns(Weapon_vec_at(weapons, 1)))); 1736 uint16_t second_weapon_damage = ns(Weapon_damage(ns(Weapon_vec_at(weapons, 1)))); 1737 ~~~ 1738 </div> 1739 1740 Last, we can access our `Equipped` FlatBuffer `union`. Just like when we created 1741 the `union`, we need to get both parts of the `union`: the type and the data. 1742 1743 We can access the type to dynamically cast the data as needed (since the 1744 `union` only stores a FlatBuffer `table`). 1745 1746 <div class="language-cpp"> 1747 ~~~{.cpp} 1748 auto union_type = monster.equipped_type(); 1749 1750 if (union_type == Equipment_Weapon) { 1751 auto weapon = static_cast<const Weapon*>(monster->equipped()); // Requires `static_cast` 1752 // to type `const Weapon*`. 1753 1754 auto weapon_name = weapon->name()->str(); // "Axe" 1755 auto weapon_damage = weapon->damage(); // 5 1756 } 1757 ~~~ 1758 </div> 1759 <div class="language-java"> 1760 ~~~{.java} 1761 int unionType = monster.EquippedType(); 1762 1763 if (unionType == Equipment.Weapon) { 1764 Weapon weapon = (Weapon)monster.equipped(new Weapon()); // Requires explicit cast 1765 // to `Weapon`. 1766 1767 String weaponName = weapon.name(); // "Axe" 1768 short weaponDamage = weapon.damage(); // 5 1769 } 1770 ~~~ 1771 </div> 1772 <div class="language-csharp"> 1773 ~~~{.cs} 1774 var unionType = monster.EquippedType; 1775 1776 if (unionType == Equipment.Weapon) { 1777 var weapon = monster.Equipped<Weapon>().Value; 1778 1779 var weaponName = weapon.Name; // "Axe" 1780 var weaponDamage = weapon.Damage; // 5 1781 } 1782 ~~~ 1783 </div> 1784 <div class="language-go"> 1785 ~~~{.go} 1786 // We need a `flatbuffers.Table` to capture the output of the 1787 // `monster.Equipped()` function. 1788 unionTable := new(flatbuffers.Table) 1789 1790 if monster.Equipped(unionTable) { 1791 unionType := monster.EquippedType() 1792 1793 if unionType == sample.EquipmentWeapon { 1794 // Create a `sample.Weapon` object that can be initialized with the contents 1795 // of the `flatbuffers.Table` (`unionTable`), which was populated by 1796 // `monster.Equipped()`. 1797 unionWeapon = new(sample.Weapon) 1798 unionWeapon.Init(unionTable.Bytes, unionTable.Pos) 1799 1800 weaponName = unionWeapon.Name() 1801 weaponDamage = unionWeapon.Damage() 1802 } 1803 } 1804 ~~~ 1805 </div> 1806 <div class="language-python"> 1807 ~~~{.py} 1808 union_type = monster.EquippedType() 1809 1810 if union_type == MyGame.Sample.Equipment.Equipment().Weapon: 1811 # `monster.Equipped()` returns a `flatbuffers.Table`, which can be used to 1812 # initialize a `MyGame.Sample.Weapon.Weapon()`. 1813 union_weapon = MyGame.Sample.Weapon.Weapon() 1814 union_weapon.Init(monster.Equipped().Bytes, monster.Equipped().Pos) 1815 1816 weapon_name = union_weapon.Name() // 'Axe' 1817 weapon_damage = union_weapon.Damage() // 5 1818 ~~~ 1819 </div> 1820 <div class="language-javascript"> 1821 ~~~{.js} 1822 var unionType = monster.equippedType(); 1823 1824 if (unionType == MyGame.Sample.Equipment.Weapon) { 1825 var weapon_name = monster.equipped(new MyGame.Sample.Weapon()).name(); // 'Axe' 1826 var weapon_damage = monster.equipped(new MyGame.Sample.Weapon()).damage(); // 5 1827 } 1828 ~~~ 1829 </div> 1830 <div class="language-php"> 1831 ~~~{.php} 1832 $union_type = $monster->getEquippedType(); 1833 1834 if ($union_type == \MyGame\Sample\Equipment::Weapon) { 1835 $weapon_name = $monster->getEquipped(new \MyGame\Sample\Weapon())->getName(); // "Axe" 1836 $weapon_damage = $monster->getEquipped(new \MyGame\Sample\Weapon())->getDamage(); // 5 1837 } 1838 ~~~ 1839 </div> 1840 <div class="language-c"> 1841 ~~~{.c} 1842 // Access union type field. 1843 if (ns(Monster_equipped_type(monster)) == ns(Equipment_Weapon)) { 1844 // Cast to appropriate type: 1845 // C allows for silent void pointer assignment, so we need no explicit cast. 1846 ns(Weapon_table_t) weapon = ns(Monster_equipped(monster)); 1847 const char *weapon_name = ns(Weapon_name(weapon)); // "Axe" 1848 uint16_t weapon_damage = ns(Weapon_damage(weapon)); // 5 1849 } 1850 ~~~ 1851 </div> 1852 1853 ## Mutating FlatBuffers 1854 1855 As you saw above, typically once you have created a FlatBuffer, it is read-only 1856 from that moment on. There are, however, cases where you have just received a 1857 FlatBuffer, and you'd like to modify something about it before sending it on to 1858 another recipient. With the above functionality, you'd have to generate an 1859 entirely new FlatBuffer, while tracking what you modified in your own data 1860 structures. This is inconvenient. 1861 1862 For this reason FlatBuffers can also be mutated in-place. While this is great 1863 for making small fixes to an existing buffer, you generally want to create 1864 buffers from scratch whenever possible, since it is much more efficient and the 1865 API is much more general purpose. 1866 1867 To get non-const accessors, invoke `flatc` with `--gen-mutable`. 1868 1869 Similar to how we read fields using the accessors above, we can now use the 1870 mutators like so: 1871 1872 <div class="language-cpp"> 1873 ~~~{.cpp} 1874 auto monster = GetMutableMonster(buffer_pointer); // non-const 1875 monster->mutate_hp(10); // Set the table `hp` field. 1876 monster->mutable_pos()->mutate_z(4); // Set struct field. 1877 monster->mutable_inventory()->Mutate(0, 1); // Set vector element. 1878 ~~~ 1879 </div> 1880 <div class="language-java"> 1881 ~~~{.java} 1882 Monster monster = Monster.getRootAsMonster(buf); 1883 monster.mutateHp(10); // Set table field. 1884 monster.pos().mutateZ(4); // Set struct field. 1885 monster.mutateInventory(0, 1); // Set vector element. 1886 ~~~ 1887 </div> 1888 <div class="language-csharp"> 1889 ~~~{.cs} 1890 var monster = Monster.GetRootAsMonster(buf); 1891 monster.MutateHp(10); // Set table field. 1892 monster.Pos.MutateZ(4); // Set struct field. 1893 monster.MutateInventory(0, 1); // Set vector element. 1894 ~~~ 1895 </div> 1896 <div class="language-go"> 1897 ~~~{.go} 1898 <API for mutating FlatBuffers is not yet available in Go.> 1899 ~~~ 1900 </div> 1901 <div class="language-python"> 1902 ~~~{.py} 1903 <API for mutating FlatBuffers is not yet available in Python.> 1904 ~~~ 1905 </div> 1906 <div class="language-javascript"> 1907 ~~~{.js} 1908 <API for mutating FlatBuffers is not yet support in JavaScript.> 1909 ~~~ 1910 </div> 1911 <div class="language-php"> 1912 ~~~{.php} 1913 <API for mutating FlatBuffers is not yet supported in PHP.> 1914 ~~~ 1915 </div> 1916 <div class="language-c"> 1917 ~~~{.c} 1918 <API for in-place mutating FlatBuffers will not be supported in C 1919 (except in-place vector sorting is possible).> 1920 ~~~ 1921 </div> 1922 1923 We use the somewhat verbose term `mutate` instead of `set` to indicate that this 1924 is a special use case, not to be confused with the default way of constructing 1925 FlatBuffer data. 1926 1927 After the above mutations, you can send on the FlatBuffer to a new recipient 1928 without any further work! 1929 1930 Note that any `mutate` functions on a table will return a boolean, which is 1931 `false` if the field we're trying to set is not present in the buffer. Fields 1932 that are not present if they weren't set, or even if they happen to be equal to 1933 the default value. For example, in the creation code above, the `mana` 1934 field is equal to `150`, which is the default value, so it was never stored in 1935 the buffer. Trying to call the corresponding `mutate` method for `mana` on such 1936 data will return `false`, and the value won't actually be modified! 1937 1938 One way to solve this is to call `ForceDefaults` on a FlatBufferBuilder to 1939 force all fields you set to actually be written. This, of course, increases the 1940 size of the buffer somewhat, but this may be acceptable for a mutable buffer. 1941 1942 If this is not sufficient, other ways of mutating FlatBuffers may be supported 1943 in your language through an object based API (`--gen-object-api`) or reflection. 1944 See the individual language documents for support. 1945 1946 ## JSON with FlatBuffers 1947 1948 #### Using `flatc` as a Conversion Tool 1949 1950 This is often the preferred method to use JSON with FlatBuffers, as it doesn't 1951 require you to add any new code to your program. It is also efficient, since you 1952 can ship with the binary data. The drawback is that it requires an extra step 1953 for your users/developers to perform (although it may be able to be automated 1954 as part of your compilation). 1955 1956 Lets say you have a JSON file that describes your monster. In this example, 1957 we will use the file `flatbuffers/samples/monsterdata.json`. 1958 1959 Here are the contents of the file: 1960 1961 ~~~{.json} 1962 { 1963 pos: { 1964 x: 1, 1965 y: 2, 1966 z: 3 1967 }, 1968 hp: 300, 1969 name: "Orc" 1970 } 1971 ~~~ 1972 1973 You can run this file through the `flatc` compile with the `-b` flag and 1974 our `monster.fbs` schema to produce a FlatBuffer binary file. 1975 1976 ~~~{.sh} 1977 ./../flatc -b monster.fbs monsterdata.json 1978 ~~~ 1979 1980 The output of this will be a file `monsterdata.bin`, which will contain the 1981 FlatBuffer binary representation of the contents from our `.json` file. 1982 1983 <div class="language-cpp"> 1984 *Note: If you're working in C++, you can also parse JSON at runtime. See the 1985 [Use in C++](@ref flatbuffers_guide_use_cpp) section of the Programmer's 1986 Guide for more information.* 1987 </div> 1988 <div class="language-c"> 1989 *Note: If you're working in C, the `flatcc --json` (not `flatc`) 1990 compiler will generate schema specific high performance json parsers and 1991 printers that you can compile and use at runtime. The `flatc` compiler (not 1992 `flatcc`) on the other hand, is still useful for general offline json to 1993 flatbuffer conversion from a given schema. There are no current plans 1994 for `flatcc` to support this.* 1995 </div> 1996 1997 ## Advanced Features for Each Language 1998 1999 Each language has a dedicated `Use in XXX` page in the Programmer's Guide 2000 to cover the nuances of FlatBuffers in that language. 2001 2002 For your chosen language, see: 2003 2004 <div class="language-cpp"> 2005 [Use in C++](@ref flatbuffers_guide_use_cpp) 2006 </div> 2007 <div class="language-java"> 2008 [Use in Java/C#](@ref flatbuffers_guide_use_java_c-sharp) 2009 </div> 2010 <div class="language-csharp"> 2011 [Use in Java/C#](@ref flatbuffers_guide_use_java_c-sharp) 2012 </div> 2013 <div class="language-go"> 2014 [Use in Go](@ref flatbuffers_guide_use_go) 2015 </div> 2016 <div class="language-python"> 2017 [Use in Python](@ref flatbuffers_guide_use_python) 2018 </div> 2019 <div class="language-javascript"> 2020 [Use in JavaScript](@ref flatbuffers_guide_use_javascript) 2021 </div> 2022 <div class="language-php"> 2023 [Use in PHP](@ref flatbuffers_guide_use_php) 2024 </div> 2025 <div class="language-c"> 2026 [Use in C](@ref flatbuffers_guide_use_c) 2027 </div> 2028 2029 <br> 2030