
FlatBuffer란?
FlatBuffer를 사용하는 이유(장점)
단점
사용법


namespace MyGame.Sample;
enum Color:byte { Red = 0, Green, Blue = 2 }
union Equipment { Weapon } // Optionally add more tables.
struct Vec3 {
x:float;
y:float;
z:float;
}
table Monster {
pos:Vec3; // Struct.
mana:short = 150;
hp:short = 100;
name:string;
friendly:bool = false (deprecated);
inventory:[ubyte]; // Vector of scalars.
color:Color = Blue; // Enum.
weapons:[Weapon]; // Vector of tables.
equipped:Equipment; // Union.
path:[Vec3]; // Vector of structs.
}
table Weapon {
name:string;
damage:short;
}
root_type Monster;
위와 같이 스키마 작성(확장자명은 fbs로 저장해야한다.)
2. 해당 샘플에 있는 컴파일러(flatc.exe)를 통해 컴파일 해준다.
(cmd를 켜서 해당 exe가 존재하는 폴더로 이동)

출력하고 싶은 언어에 관련된 명령어 입력
// ‘platc’에 의해 생성된 것이며, 이미 “flatbuffers/flatbuffers.h”를 포함하고 있다.
#include “monster_generated.h” [두번째]```
// 'FlatBufferBuilder'를 생성합니다. 이는
// 몬스터의 FlatBuffer.
flatbuffers::FlatBufferBuilder builder(1024);
```이제 직렬화를 진행할 수 있다. auto weaponOneName = builder.CreateString("Sword");
short weaponOneDamage = 3;
auto weaponTwoName = builder.CreateString("Axe");
short weaponTwoDamage = 5;
// 'CreateWeapon' 단축키를 사용하여 모든 필드가 설정된 무기를 생성
auto sword = CreateWeapon(builder, weaponOneName, weaponOneDamage);
auto axe = CreateWeapon(builder, weaponTwoName, weaponTwoDamage);
//기존 배열에서 벡터를 생성하는 대신 요소를 하나씩 개별적으로
//직렬화하는 경우 버퍼가 뒤에서 앞으로 구축되므로 역순으로 발생한다는 점이 주의
// Create a FlatBuffer's `vector` from the `std::vector`.
std::vector<flatbuffers::Offset<Weapon>> weapons_vector;
weapons_vector.push_back(sword);
weapons_vector.push_back(axe);
auto weapons = builder.CreateVector(weapons_vector);
[네번째]
- Monster에 필요한 나머지 객체 serialize진행
Monster를 직렬화하기 전에 먼저 그 안에 포함된 모든 객체를 직렬화해야 한다. Flatbuffer는 깊이 우선을 사용하여 데이터 트리를 직렬화한다.
auto position = Vec3(1.0f, 2.0f, 3.0f);
auto name = builder.CreateString("MyMonster");
unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto inventory = builder.CreateVector(inv_data, 10);
// Shortcut for creating monster with all fields set:
auto orc = CreateMonster(builder, &position, 150, 80, name, inventory,
Color_Red, weapons, Equipment_Weapon, axe.Union());
[추가적으로]
모든 필드를 설정하고 싶지 않은 경우에는 table을 호출하는 대신 각 필드를 수동으로 설정할 수 있다.
// 수동으로 생성
MonsterBuilder monster_builder(builder);
monster_builder.add_pos(&position);
monster_builder.add_hp(hp);
monster_builder.add_name(name);
monster_builder.add_inventory(inventory);
monster_builder.add_color(Color_Red);
monster_builder.add_weapons(weapons);
monster_builder.add_equipped_type(Equipment_Weapon);
monster_builder.add_equipped(axe.Union());
auto orc = monster_builder.Finish();
//Finis()를 호출하여 빌더에게 이 몬스터가 완료되었 음을 알린다.
// 참고 : 'orc'를 어떻게 생성했는지에 관계없이 여전히 호출해야한다.
// 'FlatBufferBuilder'의 Finish()'
builder.Finish(orc); // 'FinishMonsterBuffer(builder, orc);'를 호출 할 수도 있다.
이제 버퍼를 어딘가에 저장하거나, 네트워크를 통해 전송하거나, 압축하거나, 원하는 작업을 수행할 준비가 되었다.
[다섯번째]
- 버퍼에 액세스
// `Finish()` 이후에 호출되어야 합니다.
uint8_t *buf = builder.GetBufferPointer();
int 크기 = builder.GetSize(); // 버퍼의 크기를 반환합니다.
만약 Finish()를 하지 않고 호출한다면, 에러를 발생
이제 바이트를 파일에 쓰거나 네트워크를 통해 보낼 수 있다. 파일모드(또는 전송 프로토콜)가 텍스트가 아닌 BINARY 로 설정되어 있는지 확인하자.
[여섯번째]
- Monster FlatBuffer 읽기
FlatBuffer를 성공적으로 생성했으므로 Orc 몬스터 데이터를 저장하고 네트워크를 통해 전송할 수 있다.
uint8_t *buffer_pointer = /* 방금 읽은 데이터 */ ;
auto monster = GetMonster(buffer_pointer);
// `monster`는 `Monster *` 유형입니다.
// 참고: 루트 객체 포인터는 `buffer_pointer`와 동일하지 않습니다.
// `GetMonster`는 `GetRoot<Monster>`를 호출하는 편의 함수이며,
// 후자는 루트가 아닌 유형에도 사용할 수 있습니다.
전부 공식 튜토리얼에 나오는 부분이므로 사이트 참고하면 더 이해하기 쉬울것이다.
마지막으로