Protocol Buffers のチュートリアル覚書き

前々回と前回でやっと準備が整ったので、Protocol Bufferesのチュートリアルを実行します。そのメモです。

チュートリアルの実行

Protocol Bufferesでは、.protoファイルに規定の形式でデータ構造を書いてprotocというコンパイラにかけると、getter/setterに該当するコードを自動生成してくれます。

.protoの文法は、JavaC++に似ていますが、クラス継承のような概念はありません。

データメンバーは、ネストさせたり、繰り返しを許したりできます。

詳細ドキュメントは、次のページにあります。

.protoファイルのコンパイル

今回は、addressbook.protoというファイルをコンパイルします。examplesに最初から入っていたファイルです。

protoc --cpp_out=./ ./addressbook.proto

すると、次の2つのファイルが作成されます。

  • addressbook.pb.cc
  • addressbook.pb.h

# これらのファイルは、examplesディレクトリをコンパイルした時点(http://d.hatena.ne.jp/torazuka/20111204/protobuf)で存在しましたが、protocの実行によって再度生成されます。

コンパイルしてできたこれらのファイルに、addressbookのデータ構造を扱うコードが書かれています。自分で編集する必要はありません。どういったコードが提供されるかは、APIリファレンスで確認できます。

アドレス帳にPersonを追加する

というわけで、データをやり取りしてみます。やり取りといっても、このチュートリアルでは、対ファイルだけですが。

examplesのコンパイルによって作成された、add_person_cppを実行します。

引数にデータ書き込み先のファイルが必要なので、protoc_middlemanという空ファイルを指定します。

$ ./add_person_cpp protoc_middleman
Enter person ID number: 101
Enter name: takeshi
Enter email address (blank for none): takeshi@hoge.com
Enter a phone number (or leave blank to finish): 12345678
Is this a mobile, home, or work phone? home
Enter a phone number (or leave blank to finish):

対話的にデータを入力します。これらが、protoc_middlemanに保存されます。

アドレス帳のリストを表示する

今度は、中身を取り出してみます。

あらかじめ用意されているlist_people_cppを実行します。

$ ./list_people_cpp protoc_middleman
Person ID: 101
 Name: takeshi
 E-mail address: takeshi@hoge.com
 Home phone #: 12345678

アドレス帳に格納されたデータが、整形表示されました。

これらのデータ入出力が、Protocol Bufferesの形式で行われているということのようです。

保存されているファイルの中身を確認

さらに入力してみます。

$ ./add_person_cpp protoc_middleman
Enter person ID number: 102
Enter name: haruyo
Enter email address (blank for none): haruyo@moga.com
Enter a phone number (or leave blank to finish): 987654321
Is this a mobile, home, or work phone? mobile
Enter a phone number (or leave blank to finish): 111122223
Is this a mobile, home, or work phone? work phone # 誤った入力値を与える(○work、×work phone)
Unknown phone type.  Using default. # .protoファイルで定義したデフォルト値が入る
Enter a phone number (or leave blank to finish): 555555555
Is this a mobile, home, or work phone? work
Enter a phone number (or leave blank to finish):

出力してみます。

$ ./list_people_cpp protoc_middleman
Person ID: 101
 Name: takeshi
 E-mail address: takeshi@hoge.com
 Home phone #: 12345678
Person ID: 102
 Name: haruyo
 E-mail address: haruyo@moga.com
 Mobile phone #: 987654321
 Home phone #: 111122223
 Work phone #: 555555555

protoc_middlemanの中身を確認すると、こんな感じになっています。

普通に開いても読めないので、バイナリを表示します。

$ od -tc protoc_middleman
0000000  \n   +  \n  \a   t   a   k   e   s   h   i 020   e 032 020   t
0000020   a   k   e   s   h   i   @   h   o   g   e   .   c   o   m   "
0000040  \f  \n  \b   1 2 3 4 5 6 7 8 020 001  \n   F  \n
0000060 006   h   a   r   u   y   o 020   f 032 017   h   a   r   u   y
0000100   o   @   m   o   g   a   .   c   o   m   "  \r  \n  \t   9   8
0000120   7 6 5 4 3 2 1 020  \0   "  \v  \n  \t   1   1   1
0000140   1   2   2   2   2   3   "  \r  \n  \t   5   5   5   5   5   5
0000160   5   5   5 020 002
0000165

メモ

そもそも、この一連の作業の目的は、Protocol Bufferesを使うことではなく、Protocol Bufferesのコードを読むための取っ掛かりを探すことでした。そうだったんかって感じですが、そうだったんですよ奥さん…。しかし、このチュートリアルだけをやっても、自分にはよくわかりませんです。トホホ

ただ、IDLのエンコード部分から読むのがとっつきやすそうだとは思いました。最初は、他言語実装との差分であるこの箇所は、コードリーディングをする上でオマケ的扱いになると思っていたのですが、自動生成部分は実行結果を出力コードで確認できるので、処理の過程を追いやすいかもしれません。(気のせいかもしれません)

あと、使うかなと思ったechoサーバは、このチュートリアルでは使いどころがありませんでした。そういうサンプルは自分で書けってことですよね、きっと。