まくろぐ
更新: / 作成:

Protcol Buffers とは

プロトコルバッファー (Protocol Buffers、または protobuf) は、Google が開発した、構造化したデータをシリアライズするためのフォーマットです。 同じく Google が開発した gRPC 通信プラットフォームで採用されており、XML や JSON などのテキストベースの API より効率的な通信を行うことができるという特徴を持っています。

  • データをコンパクトに表現できるため、通信やパース処理が高速
  • 強い型付けを行うことでき、サーバー、クライアントの安全なコーディングが可能
  • 定義変更時の互換性を考慮したフォーマット
  • OS やプログラミング言語などに非依存

データ構造やサービス形式の定義は、.proto 拡張子を持つ プロトコル定義ファイル (Proto Definition file) で行います。 この .proto ファイルを protoc コマンド(プロトコルバッファーコンパイラ)でコンパイルすると、各言語用のソースコードを生成することができます。

/p/37e6uck/img-001.drawio.svg
図: protoc コマンドによるコード生成

protoc コマンドは各種プログラミング言語用のコードを生成するわけですが、そのためには、protoc コマンド本体各言語用のプラグインprotoc-gen-go など)がインストールされている必要があります。 C++ や C#、Kotlin、Python、Ruby などのコード生成は組み込みで対応していますが、Go 言語用のプラグインなどは別途インストールする必要があります。

protoc 本体のインストール

protoc コマンド (Protocol Buffers Compiler) は、Linux(Ubuntu 系)や macOS ではパッケージマネージャーを使ってインストールしてしまうのが簡単です。 インストールするパッケージの名前は protobufprotobuf-compiler であることに注意してください。

macOS (Homebrew) の場合

$ brew install protobuf  # インストール
$ brew upgrade protobuf  # バージョン更新

Linux (apt) の場合

$ apt install -y protobuf-compiler

プリビルド版を使う場合

あるいは、各 OS 用のバイナリを GitHub のリリースページ からダウンロードし、protoc コマンドにパスを通します。 例えば、Windows であれば protoc-3.20.0-win64.zip などをダウンロードします。

次のように protoc コマンドを実行できるようになれば OK です。

$ protoc --version
libprotoc 3.20.0

.proto ファイルをコンパイルしてみる

次のような簡単な .proto ファイルを入力ファイルとして用意します。

proto/person.proto
syntax = "proto3";

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

C# のコードを生成

例えば、次のように実行すると、C# 用のソースコードを生成することができます。 --csharp_out=<OUT_DIR> というオプションで、C# ソースコードの出力先ディレクトリを指定しています。

$ mkdir gen
$ protoc --csharp_out=gen proto/person.proto
$ ls gen
Person.cs

Python のコードを生成

Python 用のソースコードを生成したければ、同様に次のようにします。 出力ディレクトリは --python_out=<OUT_DIR> オプションで指定します。

$ protoc --python_out=gen proto/person.proto

その他の言語のコードを生成

他にも各言語用のソースコードを生成するオプションが用意されており、次のようにヘルプ表示すると標準でサポートしている言語を確認できます。

protoc の言語別出力オプション
$ protoc --help | grep OUT_DIR
  --cpp_out=OUT_DIR           Generate C++ header and source.
  --csharp_out=OUT_DIR        Generate C# source file.
  --java_out=OUT_DIR          Generate Java source file.
  --js_out=OUT_DIR            Generate JavaScript source.
  --kotlin_out=OUT_DIR        Generate Kotlin file.
  --objc_out=OUT_DIR          Generate Objective-C header and source.
  --php_out=OUT_DIR           Generate PHP source file.
  --python_out=OUT_DIR        Generate Python source file.
  --ruby_out=OUT_DIR          Generate Ruby source file.

言語拡張 (protoc-gen-xxx)

protoc が標準でサポートしてない言語のコードを生成するには、追加のプラグイン(実際はただのコマンド)をインストールする必要があります。 追加でインストールするコマンドは protoc-gen-<言語名> という名前であり、そのコマンドがシステムに存在していると、protoc コマンドの --<言語名>_out というオプションが有効になります。

例: Go 言語用プラグイン (protoc-gen-go)

例えば、Go 言語用のプラグインである protoc-gen-go をインストールすると、--go_out オプションが使えるようになります。

protoc-gen-go のインストール
# バージョン指定でインストールする場合(推奨)
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.0

# 最新版をインストールする場合
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

# 確認
$ protoc-gen-go --version
protoc-gen-go v1.28.0

Go 言語用のコードを出力する場合は、.proto ファイル内の option go_package でパッケージ名を設定しておく必要があります。

proto/person.proto
syntax = "proto3";

option go_package = "example.com/myapp";

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

次のようにすると、gen ディレクトリ以下に Go コードが生成されます。

$ protoc --go_out=gen proto/person.proto

.proto ファイルで指定したパッケージ名に従ってディレクトリ階層ができます。

gen/example.com/myapp/person.pb.go

.proto ファイル内でパッケージ名を指定するのではなく、protoc コマンドの --go_opt=M... オプションで次のように指定することもできます。

$ protoc --go_out=gen \
         --go_opt=Mproto/person.proto=example.com/myapp \
         proto/person.proto

= が 2 回出てくるのでちょっと分かりにくいですが、proto/person.proto ファイルのパッケージ名を example.com/myapp に設定しています。

まくろぐ
サイトマップまくへのメッセージ