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 が本当に遅いのか実際に確かめてみた