protocol buffer 3 をビルドしてインストール
最近 version 3 が出た protobuf を試しに動かしてみたメモ。
導入手順
Releases から C++ のアーカイブをダウンロードしてきて展開する。(protobuf-cpp-3.0.0.tar.gz というやつ)
展開後のディレクトリに cd して、以下の手順でビルドする。
./configure make -j $(nproc)
後は、sudo make install && sudo ldconfig すればインストールできるが、個人的に野良インストールはしたくないので、deb パッケージを作ることにする。別に deb を作りたくない人はこの手順は無視してOK。
# ./deb に make install する mkdir deb make install DESTDIR=$(pwd)/deb mkdir ./deb/DEBIAN # control ファイルを書く cat > ./deb/DEBIAN/control <<EOF Package: nojima-protobuf Version: 3.0.0-1 Maintainer: Nobody <nobody@example.com> Architecture: amd64 Description: protocol buffer EOF # postinst スクリプトを書く (ldconfig するだけ) cat > ./deb/DEBIAN/postinst <<EOF #!/bin/sh -e ldconfig EOF chmod +x ./deb/DEBIAN/postinst # deb パッケージ化する fakeroot dpkg-deb --build -Z gzip ./deb ./ # できた deb パッケージをインストールする sudo dpkg -i ./nojima-protobuf_3.0.0-1_amd64.deb
試しに動かしてみる
以下の内容を person.proto という名前で保存する。
syntax = "proto3";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
}
protoc でコンパイルして C++ のソースコードを生成する。
protoc --cpp_out=./ person.proto
すると person.pb.h と person.pb.cc というファイルができる。
これを使って person を encode するコードを書いてみる。
以下の内容を encode_person.cc という名前で保存する。
#include <cstdlib>
#include <fstream>
#include <iostream>
#include "person.pb.h"
int main(int argc, char** argv) {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != 2) {
std::cerr << "Usage: encode_person FILE\n";
std::exit(1);
}
Person person;
person.set_name("Yusuke Nojima");
person.set_id(42);
person.set_email("nojima@example.com");
std::fstream output(argv[1], std::ios::out|std::ios::trunc|std::ios::binary);
if (!output) {
std::cerr << "ERROR: failed to open file: " << argv[1] << "\n";
std::exit(1);
}
if (!person.SerializeToOstream(&output)) {
std::cerr << "ERROR: failed to serialize person.\n";
std::exit(1);
}
return 0;
}
そしてコンパイルして実行。
g++ -Wall -o encode_person encode_person.cc person.pb.cc -l protobuf ./encode_person person01
すると person01 というファイルにそれっぽい何かが出力される。
$ xxd person01 00000000: 0a0d 5975 7375 6b65 204e 6f6a 696d 6110 ..Yusuke Nojima. 00000010: 2a1a 126e 6f6a 696d 6140 6578 616d 706c *..nojima@exampl 00000020: 652e 636f 6d e.com
次に、シリアライズされた person を decode するものを書いてみる。
以下の内容を decode_person.cc という名前で保存する。
#include <cstdlib>
#include <fstream>
#include <iostream>
#include "person.pb.h"
int main(int argc, char** argv) {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != 2) {
std::cerr << "Usage: decode_person FILE\n";
std::exit(1);
}
std::fstream input(argv[1], std::ios::in|std::ios::binary);
if (!input) {
std::cerr << "ERROR: failed to open file: " << argv[1] << "\n";
std::exit(1);
}
Person person;
if (!person.ParseFromIstream(&input)) {
std::cerr << "ERROR: failed to parse person.\n";
std::exit(1);
}
std::cout << "name = " << person.name() << "\n";
std::cout << "id = " << person.id() << "\n";
std::cout << "email = " << person.email() << "\n";
return 0;
}
そしてコンパイルして実行。
$ g++ -Wall -o decode_person decode_person.cc person.pb.cc -l protobuf $ ./decode_person person01 name = Yusuke Nojima id = 42 email = nojima@example.com
読めた!!
TODO
ベンチマーク取りたい。
[追記] ベンチマーク取った → Protocol Buffers が本当に遅いのか実際に確かめてみた