公式ドキュメントが英語で、日本語の情報があまりみつからないので、やってみてまとめます。
公式チュートリアルは1ファイルで書き読みやってるけど、今回は書き・読み2ファイルに分けます。
FlatBuffersとは
Google社が開発しているクロスプラットフォーム対応のシリアライゼーションライブラリ。
Jsonと違い、パースやunpackingが不要でデータにアクセスできるので高速。
Cocos2d-x、FacebookのAndroidアプリなどで使われている。
https://google.github.io/flatbuffers/index.html
環境
centos8、PHP7.4
作業ディレクトリ作成
mkdir fbwork cd fbwork
FlatBuffersをクローン
git clone https://github.com/google/flatbuffers.git
flatbuffers/php/下にphp用のライブラリがある
flatc(FlatBuffersのコンパイラ)をビルド(初回のみ)
yum install gcc-c++ cmake cd flatbuffers cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release make ln -s /flatbuffersのフルパス/flatc /usr/local/bin/flatc cd ../
スキーマを作成
vi monster.fbs
namespace MyGame.Sample; enum Color:byte { Red = 0, Green, Blue = 2 } struct Vec3 { x:float; y:float; z:float; } table Monster { pos:Vec3; hp:short = 100; name:string; color:Color = Blue; weapons:[Weapon]; } table Weapon { name:string; damage:short; } root_type Monster;
スキーマをコンパイル
flatc --php monster.fbs
MyGame/Sample/以下にファイルが作成される
Color.php Monster.php Vec3.php Weapon.php
書き込みサンプル
vi WriteSample.php
<?php function __autoload($class_name) { $class = substr($class_name, strrpos($class_name, "\\") + 1); $root_dir = dirname(__FILE__); $paths = array(join(DIRECTORY_SEPARATOR, array($root_dir, "flatbuffers", "php")), join(DIRECTORY_SEPARATOR, array($root_dir, "MyGame", "Sample"))); foreach ($paths as $path) { $file = join(DIRECTORY_SEPARATOR, array($path, $class . ".php")); if (file_exists($file)) { require($file); break; } } } $builder = new \Google\FlatBuffers\FlatbufferBuilder(1024); $weapon_one_name = $builder->createString("Sword"); $sword = \MyGame\Sample\Weapon::CreateWeapon($builder, $weapon_one_name, 3); $weapon_two_name = $builder->createString("Axe"); $axe = \MyGame\Sample\Weapon::CreateWeapon($builder, $weapon_two_name, 5); $weaps = array($sword, $axe); $weapons = \MyGame\Sample\Monster::CreateWeaponsVector($builder, $weaps); $name = $builder->createString("Orc"); $pos = \MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0); \MyGame\Sample\Monster::StartMonster($builder); \MyGame\Sample\Monster::AddPos($builder, $pos); \MyGame\Sample\Monster::AddHp($builder, 300); \MyGame\Sample\Monster::AddName($builder, $name); \MyGame\Sample\Monster::AddColor($builder, \MyGame\Sample\Color::Red); \MyGame\Sample\Monster::AddWeapons($builder, $weapons); $orc = \MyGame\Sample\Monster::EndMonster($builder); $builder->finish($orc); file_put_contents("monster.dat", $builder->sizedByteArray());
php WriteSample.phpと実行すると、バイナリファイル(monster.dat)が生成される。
読み込みサンプル
vi ReadSample.php
<?php function __autoload($class_name) { $class = substr($class_name, strrpos($class_name, "\\") + 1); $root_dir = dirname(__FILE__); $paths = array(join(DIRECTORY_SEPARATOR, array($root_dir, "flatbuffers", "php")), join(DIRECTORY_SEPARATOR, array($root_dir, "MyGame", "Sample"))); foreach ($paths as $path) { $file = join(DIRECTORY_SEPARATOR, array($path, $class . ".php")); if (file_exists($file)) { require($file); break; } } } $contents = file_get_contents("monster.dat"); $bb = \Google\FlatBuffers\ByteBuffer::wrap($contents); $monster = \MyGame\Sample\Monster::GetRootAsMonster($bb); echo $monster->getHp() . "\n"; echo $monster->getName() . "\n"; echo $monster->getColor() . "\n"; echo $monster->getPos()->getX() . "\n"; echo $monster->getPos()->getY() . "\n"; echo $monster->getPos()->getZ() . "\n";
php ReadSample.phpと実行すると、バイナリファイル(monster.dat)を読み込んだ結果を表示します。
FlatBufferバイナリをJSONにパース
flatc --json --raw-binary monster.fbs -- monster.dat
参考
公式チュートリアル
https://google.github.io/flatbuffers/flatbuffers_guide_tutorial.html
FlatBuffersをPHPで使ってみる
https://labs.gree.jp/blog/2015/11/14495/