protobufを使ってみた。

google protobufを使ってみたので、installからの手順を残しておきます。

#### [consideration]
通信フレームワークは、ROSなどがロボティクス系では有名ですが、protobufは対応言語も多くサポートしているので、プロセス間通信などで簡単に導入ができそうです。ただし、処理量が気になるので、適用時には要件を満たすか確認が必要だと思います。

#### [install]
今回は、C++ versionで試しています。
(それでなくとも遅そうなので、Nativeを使う以外選択肢はなさそうなので。。)

以下は、Ubuntu16.04で試しています。

C++のinstallは以下に記載されています。
https://github.com/google/protobuf/tree/master/src

```shell-session
$ sudo apt-get install autoconf automake libtool curl make g++ unzip
$ ./autogen.sh
$ ./configure
$ make
$ make check
$ sudo make install
$ sudo ldconfig # refresh shared library cache.

debian packageをapt-getしてもいいですが、Ubuntuのdebian packageはversionが少し古いです。
sample codeをbuildしようとするとerrorが出るので、要修正です。

$ sudo apt-get install libprotobuf-dev libprotoc-dev protobuf-compiler
$ protoc --version
libprotoc 2.6.1
$ dpkg -l | grep protobuf
ii  libmirprotobuf3:i386                                        0.21.0+16.04.20160330-0ubuntu1                        i386         Display server for Ubuntu - RPC definitions
ii  libprotobuf-dev:i386                                        2.6.1-1.3                                             i386         protocol buffers C++ library (development files)
rc  libprotobuf-lite8:i386                                      2.5.0-9ubuntu1                                        i386         protocol buffers C++ library (lite version)
ii  libprotobuf-lite9v5:i386                                    2.6.1-1.3                                             i386         protocol buffers C++ library (lite version)
rc  libprotobuf8:i386                                           2.5.0-9ubuntu1                                        i386         protocol buffers C++ library
ii  libprotobuf9v5:i386                                         2.6.1-1.3                                             i386         protocol buffers C++ library
ii  protobuf-compiler                                           2.6.1-1.3                                             i386         compiler for protocol buffer definition files
```

#### [How To Use]
protobuf/examplesを参考にしています。

大きく手順は、以下の3つです。
[1] IF定義、.protoファイルの作成。

IFファイルは、以下の通りversion 2でもcompileできるように修正。

```protobuf
package tutorial;

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}
```

[2] protocによるコンパイル。

```shell-session
$ protoc --cpp_out=. --java_out=. --python_out=. addressbook.proto
```

[3] APIを利用してsend/receiveアプリを作る。
```shell-session
$ c++ add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf`
$ c++ list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf`
```

#### [execution example]
IFとしては、PersonがAddressBookとして配列構造となっているだけ。
required/optional/repeatedはその通りの意味で、必須property/オプションproperty(なくても良い)/繰り返しpropertyといった感じです。

add_person.ccは、指定したファイルにCLIからpropertyを入力して、serializeするだけ。
list_person.ccは、serializeされたファイルをde-serializeして出力。

```shell-session
$ ./add_person_cpp phonebook
phonebook: File not found.  Creating a new file.
Enter person ID number: 12
Enter name: TomoyaFujita
Enter email address (blank for none): Tomoya.Fujita@hoge.com
Enter a phone number (or leave blank to finish): 1234567890
Is this a mobile, home, or work phone? mobile
Enter a phone number (or leave blank to finish):

$ ls -lt phonebook
-rw-r--r-- 1 tomoyafujita tomoyafujita 58 Feb  9 23:39 phonebook

$ ./list_people_cpp phonebook
Person ID: 12
  Name: TomoyaFujita
  E-mail address: Tomoya.Fujita@hoge.com
  Mobile phone #: 1234567890
```

#### [tips]
・APIも豊富に提供してくれるので楽。
・使い勝手も非常に簡単。
・google曰く、c++版は"extremely optimized"らしい。(処理量を気にするなら、nativeが一番)


#### [reference]
[protobuf](https://github.com/google/protobuf)
[cpptutorial](https://developers.google.com/protocol-buffers/docs/cpptutorial)
[C++ API] (https://developers.google.com/protocol-buffers/docs/reference/cpp/)