C++ で生成されたコードのガイド

特定のプロトコル定義に対してプロトコル バッファ コンパイラが生成する C++ コードの内容を正確に記述します。

proto2 と proto3 で生成されたコードの相違点が強調表示されています。これらの相違点は、このドキュメントで説明されている生成されたコードにあり、両方のバージョンで同じ基本メッセージ クラス/インターフェースにはないことに注意してください。このドキュメントを読む前に、proto2 言語ガイドおよび/またはproto3 言語ガイドを読む必要があります。

コンパイラの呼び出し

プロトコル バッファ コンパイラは、--cpp_out= コマンドライン フラグを指定して呼び出すと、C++ 出力を生成します。--cpp_out= オプションのパラメータは、コンパイラに C++ 出力を書き込ませたいディレクトリです。コンパイラは、入力の各 .proto ファイルに対して、ヘッダー ファイルと実装ファイルを作成します。出力ファイルの名前は、.proto ファイルの名前を取得し、次の 2 つの変更を加えることで計算されます。

  • 拡張子 (.proto) は、ヘッダー ファイルの場合は .pb.h、実装ファイルの場合は .pb.cc に置き換えられます。
  • proto パス (--proto_path= または -I コマンドライン フラグで指定) は、出力パス (--cpp_out= フラグで指定) に置き換えられます。

たとえば、次のようにコンパイラを呼び出すとします。

protoc --proto_path=src --cpp_out=build/gen src/foo.proto src/bar/baz.proto

コンパイラは、src/foo.proto ファイルと src/bar/baz.proto ファイルを読み取り、4 つの出力ファイル (build/gen/foo.pb.hbuild/gen/foo.pb.ccbuild/gen/bar/baz.pb.hbuild/gen/bar/baz.pb.cc) を生成します。コンパイラは、必要に応じてディレクトリ build/gen/bar を自動的に作成しますが、build または build/gen は作成しません。これらは既に存在している必要があります。

パッケージ

.proto ファイルに package 宣言が含まれている場合、ファイルの内容全体が対応する C++ 名前空間に配置されます。たとえば、package 宣言が次のように指定されているとします。

package foo.bar;

ファイル内のすべての宣言は、foo::bar 名前空間に存在します。

メッセージ

単純なメッセージ宣言が与えられた場合

message Foo {}

プロトコル バッファ コンパイラは、google::protobuf::Message から公開で派生する Foo という名前のクラスを生成します。このクラスは具象クラスであり、未実装の純粋仮想メソッドは残りません。Message で仮想であるが純粋仮想ではないメソッドは、最適化モードに応じて、Foo によってオーバーライドされる場合とされない場合があります。デフォルトでは、Foo は最大の速度を得るためにすべてのメソッドの特殊化されたバージョンを実装します。ただし、.proto ファイルに次の行が含まれている場合

option optimize_for = CODE_SIZE;

Foo は機能に必要な最小限のメソッド セットのみをオーバーライドし、残りのメソッドのリフレクションベースの実装に依存します。これにより、生成されたコードのサイズが大幅に削減されますが、パフォーマンスも低下します。または、.proto ファイルに次が含まれている場合

option optimize_for = LITE_RUNTIME;

Foo はすべてのメソッドの高速実装を含みますが、google::protobuf::MessageLite インターフェースを実装します。このインターフェースには、Message のメソッドのサブセットのみが含まれています。特に、記述子またはリフレクションはサポートされていません。ただし、このモードでは、生成されたコードは libprotobuf.so (libprotobuf.lib) ではなく、libprotobuf-lite.so (Windows の場合は libprotobuf-lite.lib) に対してのみリンクする必要があります。「lite」ライブラリは、完全なライブラリよりもはるかに小さく、携帯電話などのリソースが制約されたシステムに適しています。

独自の Foo サブクラスを作成すべきではありません。このクラスをサブクラス化して仮想メソッドをオーバーライドすると、オーバーライドは無視される可能性があります。多くの生成されたメソッド呼び出しは、パフォーマンスを向上させるために非仮想化されるためです。

Message インターフェースは、バイナリ文字列との間の解析とシリアライズを含む、メッセージ全体をチェック、操作、読み取り、または書き込みできるメソッドを定義します。

  • bool ParseFromString(::absl::string_view data): 指定されたシリアライズされたバイナリ文字列 (ワイヤー フォーマットとも呼ばれます) からメッセージを解析します。
  • bool SerializeToString(string* output) const: 指定されたメッセージをバイナリ文字列にシリアライズします。
  • string DebugString(): proto の text_format 表現を与える文字列を返します (デバッグにのみ使用する必要があります)。

これらのメソッドに加えて、Foo クラスは次のメソッドを定義します。

  • Foo(): デフォルト コンストラクタ。
  • ~Foo(): デフォルト デストラクタ。
  • Foo(const Foo& other): コピー コンストラクタ。
  • Foo(Foo&& other): ムーブ コンストラクタ。
  • Foo& operator=(const Foo& other): 代入演算子。
  • Foo& operator=(Foo&& other): ムーブ代入演算子。
  • void Swap(Foo* other): コンテンツを別のメッセージとスワップします。
  • const UnknownFieldSet& unknown_fields() const: このメッセージの解析中に発生した不明なフィールドのセットを返します。option optimize_for = LITE_RUNTIME.proto ファイルで指定されている場合、戻り値の型は std::string& に変わります。
  • UnknownFieldSet* mutable_unknown_fields(): このメッセージの解析中に発生した不明なフィールドの可変セットへのポインタを返します。option optimize_for = LITE_RUNTIME.proto ファイルで指定されている場合、戻り値の型は std::string* に変わります。

クラスは、次の静的メソッドも定義します。

  • static const Descriptor* descriptor(): 型の記述子を返します。これには、型が持つフィールドとその型を含む、型に関する情報が含まれています。これは、リフレクションでプログラムでフィールドを検査するために使用できます。
  • static const Foo& default_instance(): Foo の const シングルトン インスタンスを返します。これは、新しく構築された Foo のインスタンスと同一です (したがって、すべての単数フィールドは設定されておらず、すべての繰り返しフィールドは空です)。メッセージのデフォルト インスタンスは、その New() メソッドを呼び出すことでファクトリとして使用できることに注意してください。

生成されたファイル名

予約語は、生成された出力でアンダースコアが追加されます。

たとえば、次の proto3 定義構文

message MyMessage {
  string false = 1;
  string myFalse = 2;
}

次の部分的な出力を生成します。

  void clear_false_() ;
  const std::string& false_() const;
  void set_false_(Arg_&& arg, Args_... args);
  std::string* mutable_false_();
  PROTOBUF_NODISCARD std::string* release_false_();
  void set_allocated_false_(std::string* ptr);

  void clear_myfalse() ;
  const std::string& myfalse() const;
  void set_myfalse(Arg_&& arg, Args_... args);
  std::string* mutable_myfalse();
  PROTOBUF_NODISCARD std::string* release_myfalse();
  void set_allocated_myfalse(std::string* ptr);

ネストされた型

メッセージは別のメッセージ内で宣言できます。例:

message Foo {
  message Bar {}
}

この場合、コンパイラは FooFoo_Bar の 2 つのクラスを生成します。さらに、コンパイラは Foo 内に typedef を次のように生成します。

typedef Foo_Bar Bar;

これは、ネストされた型のクラスを、ネストされたクラス Foo::Bar であるかのように使用できることを意味します。ただし、C++ では、ネストされた型を前方宣言できないことに注意してください。別のファイルで Bar を前方宣言し、その宣言を使用する場合は、Foo_Bar として識別する必要があります。

フィールド

前のセクションで説明したメソッドに加えて、プロトコル バッファ コンパイラは、.proto ファイル内のメッセージ内で定義された各フィールドに対して、アクセサ メソッドのセットを生成します。これらのメソッドは、has_foo()clear_foo() のように、小文字/スネークケースです。

アクセサ メソッドと同様に、コンパイラは各フィールドに対して、そのフィールド番号を含む整数定数を生成します。定数名は、文字 k、その後にフィールド名をキャメルケースに変換したもの、その後に FieldNumber が続きます。たとえば、フィールド optional int32 foo_bar = 5; が与えられた場合、コンパイラは定数 static const int kFooBarFieldNumber = 5; を生成します。

const 参照を返すフィールド アクセサの場合、その参照は、次の変更アクセスがメッセージに対して行われたときに無効になる可能性があります。これには、任意のフィールドの非 const アクセサの呼び出し、Message から継承された非 const メソッドの呼び出し、または他の方法 (たとえば、メッセージを Swap() の引数として使用するなど) でメッセージを変更することが含まれます。対応して、返された参照のアドレスは、それまでの間にメッセージに変更アクセスが行われなかった場合にのみ、アクセサの異なる呼び出し間で同じであることが保証されます。

ポインタを返すフィールド アクセサの場合、そのポインタは、次の変更アクセスまたは非変更アクセスがメッセージに対して行われたときに無効になる可能性があります。これには、const 性に関係なく、任意のフィールドのアクセサの呼び出し、Message から継承された任意のメソッドの呼び出し、または他の方法 (たとえば、コピー コンストラクタを使用してメッセージをコピーするなど) でメッセージにアクセスすることが含まれます。対応して、返されたポインタの値は、アクセサの 2 つの異なる呼び出し間で同じであることが保証されることはありません。

オプションの数値フィールド (proto2 および proto3)

これらのフィールド定義のいずれか

optional int32 foo = 1;
required int32 foo = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • bool has_foo() const: フィールドが設定されている場合は true を返します。
  • int32 foo() const: フィールドの現在の値を返します。フィールドが設定されていない場合は、デフォルト値を返します。
  • void set_foo(int32 value): フィールドの値を設定します。これを呼び出した後、has_foo()true を返し、foo()value を返します。
  • void clear_foo(): フィールドの値をクリアします。これを呼び出した後、has_foo()false を返し、foo() はデフォルト値を返します。

他の数値フィールド型 (bool を含む) の場合、スカラー値型テーブルに従って、int32 は対応する C++ 型に置き換えられます。

暗黙的な存在の数値フィールド (proto3)

以下のフィールド定義の場合

int32 foo = 1;  // no field label specified, defaults to implicit presence.

コンパイラは、次のアクセサ メソッドを生成します。

  • int32 foo() const: フィールドの現在の値を返します。フィールドが設定されていない場合は、0 を返します。
  • void set_foo(int32 value): フィールドの値を設定します。これを呼び出した後、foo()value を返します。
  • void clear_foo(): フィールドの値をクリアします。これを呼び出した後、foo() は 0 を返します。

他の数値フィールド型 (bool を含む) の場合、スカラー値型テーブルに従って、int32 は対応する C++ 型に置き換えられます。

オプションの String/Bytes フィールド (proto2 および proto3)

注: エディション 2023 以降では、features.(pb.cpp).string_typeVIEW に設定されている場合、代わりに string_view API が生成されます。

これらのフィールド定義のいずれかの場合

optional string foo = 1;
required string foo = 1;
optional bytes foo = 1;
required bytes foo = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • bool has_foo() const: フィールドが設定されている場合は true を返します。
  • const string& foo() const: フィールドの現在の値を返します。フィールドが設定されていない場合は、デフォルト値を返します。
  • void set_foo(::absl::string_view value): フィールドの値を設定します。これを呼び出した後、has_foo()true を返し、foo()value のコピーを返します。
  • void set_foo(const string& value): フィールドの値を設定します。これを呼び出した後、has_foo()true を返し、foo()value のコピーを返します。
  • void set_foo(string&& value): フィールドの値を設定し、渡された文字列から移動します。これを呼び出した後、has_foo()true を返し、foo()value のコピーを返します。
  • void set_foo(const char* value): C スタイルの null 終端文字列を使用してフィールドの値を設定します。これを呼び出した後、has_foo()true を返し、foo()value のコピーを返します。
  • void set_foo(const char* value, int size): null 終端バイトを探して決定するのではなく、明示的にサイズが指定された文字列を使用してフィールドの値を設定します。これを呼び出した後、has_foo()true を返し、foo()value のコピーを返します。
  • string* mutable_foo(): フィールドの値を格納する可変 string オブジェクトへのポインタを返します。呼び出し前にフィールドが設定されていなかった場合、返される文字列は空になります (デフォルト値ではありません)。これを呼び出した後、has_foo()true を返し、foo() は指定された文字列に書き込まれた値を返します。
  • void clear_foo(): フィールドの値をクリアします。これを呼び出した後、has_foo()false を返し、foo() はデフォルト値を返します。
  • void set_allocated_foo(string* value): string オブジェクトをフィールドに設定し、以前のフィールド値が存在する場合は解放します。string ポインタが NULL でない場合、メッセージは割り当てられた string オブジェクトの所有権を取得し、has_foo()true を返します。メッセージはいつでも割り当てられた string オブジェクトを削除できるため、オブジェクトへの参照は無効になる可能性があります。それ以外の場合、valueNULL の場合、動作は clear_foo() を呼び出す場合と同じです。
  • string* release_foo(): フィールドの所有権を解放し、string オブジェクトのポインタを返します。これを呼び出した後、呼び出し元は割り当てられた string オブジェクトの所有権を取得し、has_foo()false を返し、foo() はデフォルト値を返します。

暗黙的な存在の String/Bytes フィールド (proto3)

注: エディション 2023 以降では、features.(pb.cpp).string_typeVIEW に設定されている場合、代わりに string_view API が生成されます。

これらのフィールド定義のいずれか

string foo = 1;  // no field label specified, defaults to implicit presence.
bytes foo = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • const string& foo() const: フィールドの現在の値を返します。フィールドが設定されていない場合は、空の文字列/空のバイトを返します。
  • void set_foo(::absl::string_view value): フィールドの値を設定します。これを呼び出した後、foo()value のコピーを返します。
  • void set_foo(const string& value): フィールドの値を設定します。これを呼び出した後、foo()value のコピーを返します。
  • void set_foo(string&& value): フィールドの値を設定し、渡された文字列から移動します。これを呼び出した後、foo()value のコピーを返します。
  • void set_foo(const char* value): C スタイルの null 終端文字列を使用してフィールドの値を設定します。これを呼び出した後、foo()value のコピーを返します。
  • void set_foo(const char* value, int size): null 終端バイトを探して決定するのではなく、明示的にサイズが指定された文字列を使用してフィールドの値を設定します。これを呼び出した後、foo()value のコピーを返します。
  • string* mutable_foo(): フィールドの値を格納する可変 string オブジェクトへのポインタを返します。呼び出し前にフィールドが設定されていなかった場合、返される文字列は空になります。これを呼び出した後、foo() は指定された文字列に書き込まれた値を返します。
  • void clear_foo(): フィールドの値をクリアします。これを呼び出した後、foo() は空の文字列/空のバイトを返します。
  • void set_allocated_foo(string* value): string オブジェクトをフィールドに設定し、以前のフィールド値が存在する場合は解放します。string ポインタが NULL でない場合、メッセージは割り当てられた string オブジェクトの所有権を取得します。メッセージはいつでも割り当てられた string オブジェクトを削除できるため、オブジェクトへの参照は無効になる可能性があります。それ以外の場合、valueNULL の場合、動作は clear_foo() を呼び出す場合と同じです。
  • string* release_foo(): フィールドの所有権を解放し、string オブジェクトのポインタを返します。これを呼び出した後、呼び出し元は割り当てられた string オブジェクトの所有権を取得し、foo() は空の文字列/空のバイトを返します。

Cord サポート付きの単数 Bytes フィールド

v23.0 では、単数 bytes フィールド (oneof フィールドを含む) の absl::Cord のサポートが追加されました。単数 stringrepeated string、および repeated bytes フィールドは、Cord の使用をサポートしていません。

単数 bytes フィールドを absl::Cord を使用してデータを格納するように設定するには、次の構文を使用します。

optional bytes foo = 25 [ctype=CORD];
bytes bar = 26 [ctype=CORD];

cord の使用は、repeated bytes フィールドでは使用できません。Protoc は、これらのフィールドの [ctype=CORD] 設定を無視します。

コンパイラは、次のアクセサ メソッドを生成します。

  • const ::absl::Cord& foo() const: フィールドの現在の値を返します。フィールドが設定されていない場合は、空の Cord (proto3) またはデフォルト値 (proto2) を返します。
  • void set_foo(const ::absl::Cord& value): フィールドの値を設定します。これを呼び出した後、foo()value を返します。
  • void set_foo(::absl::string_view value): フィールドの値を設定します。これを呼び出した後、foo()absl::Cord として value を返します。
  • void clear_foo(): フィールドの値をクリアします。これを呼び出した後、foo() は空の Cord (proto3) またはデフォルト値 (proto2) を返します。
  • bool has_foo(): フィールドが設定されている場合は true を返します。

オプションの Enum フィールド (proto2 および proto3)

enum 型が与えられた場合

enum Bar {
  BAR_UNSPECIFIED = 0;
  BAR_VALUE = 1;
  BAR_OTHER_VALUE = 2;
}

これらのフィールド定義のいずれか

optional Bar bar = 1;
required Bar bar = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • bool has_bar() const: フィールドが設定されている場合は true を返します。
  • Bar bar() const: フィールドの現在の値を返します。フィールドが設定されていない場合は、デフォルト値を返します。
  • void set_bar(Bar value): フィールドの値を設定します。これを呼び出した後、has_bar()true を返し、bar()value を返します。デバッグ モード (つまり、NDEBUG が定義されていない場合) では、valueBar に定義された値のいずれとも一致しない場合、このメソッドはプロセスを中止します。
  • void clear_bar(): フィールドの値をクリアします。これを呼び出した後、has_bar()false を返し、bar() はデフォルト値を返します。

暗黙的な存在の Enum フィールド (proto3)

enum 型が与えられた場合

enum Bar {
  BAR_UNSPECIFIED = 0;
  BAR_VALUE = 1;
  BAR_OTHER_VALUE = 2;
}

このフィールド定義の場合

Bar bar = 1;  // no field label specified, defaults to implicit presence.

コンパイラは、次のアクセサ メソッドを生成します。

  • Bar bar() const: フィールドの現在の値を返します。フィールドが設定されていない場合は、デフォルト値 (0) を返します。
  • void set_bar(Bar value): フィールドの値を設定します。これを呼び出した後、bar()value を返します。
  • void clear_bar(): フィールドの値をクリアします。これを呼び出した後、bar() はデフォルト値を返します。

オプションの埋め込みメッセージ フィールド (proto2 および proto3)

メッセージ型が与えられた場合

message Bar {}

これらのフィールド定義のいずれかの場合

//proto2
optional Bar bar = 1;
required Bar bar = 1;

//proto3
Bar bar = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • bool has_bar() const: フィールドが設定されている場合は true を返します。
  • const Bar& bar() const: フィールドの現在の値を返します。フィールドが設定されていない場合は、フィールドが設定されていない Bar (おそらく Bar::default_instance()) を返します。
  • Bar* mutable_bar(): フィールドの値を格納する可変 Bar オブジェクトへのポインタを返します。呼び出し前にフィールドが設定されていなかった場合、返される Bar にはフィールドが設定されていません (つまり、新しく割り当てられた Bar と同一になります)。これを呼び出した後、has_bar()true を返し、bar()Bar の同じインスタンスへの参照を返します。
  • void clear_bar(): フィールドの値をクリアします。これを呼び出した後、has_bar()false を返し、bar() はデフォルト値を返します。
  • void set_allocated_bar(Bar* bar): Bar オブジェクトをフィールドに設定し、以前のフィールド値が存在する場合は解放します。Bar ポインタが NULL でない場合、メッセージは割り当てられた Bar オブジェクトの所有権を取得し、has_bar()true を返します。それ以外の場合、BarNULL の場合、動作は clear_bar() を呼び出す場合と同じです。
  • Bar* release_bar(): フィールドの所有権を解放し、Bar オブジェクトのポインタを返します。これを呼び出した後、呼び出し元は割り当てられた Bar オブジェクトの所有権を取得し、has_bar()false を返し、bar() はデフォルト値を返します。

繰り返し数値フィールド

このフィールド定義の場合

repeated int32 foo = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • int foo_size() const: フィールドに現在存在する要素の数を返します。空のセットを確認するには、このメソッドの代わりに、基になる RepeatedFieldempty() メソッドの使用を検討してください。
  • int32 foo(int index) const: 指定された 0 から始まるインデックスにある要素を返します。このメソッドを [0, foo_size()) の範囲外のインデックスで呼び出すと、未定義の動作になります。
  • void set_foo(int index, int32 value): 指定された 0 から始まるインデックスにある要素の値を設定します。
  • void add_foo(int32 value): 指定された値を持つ新しい要素をフィールドの最後に追加します。
  • void clear_foo(): フィールドからすべての要素を削除します。これを呼び出した後、foo_size() はゼロを返します。
  • const RepeatedField<int32>& foo() const: フィールドの要素を格納する基になる RepeatedField を返します。このコンテナ クラスは、STL のようなイテレータやその他のメソッドを提供します。
  • RepeatedField<int32>* mutable_foo(): フィールドの要素を格納する基になる可変 RepeatedField へのポインタを返します。このコンテナ クラスは、STL のようなイテレータやその他のメソッドを提供します。

他の数値フィールド型 (bool を含む) の場合、スカラー値型テーブルに従って、int32 は対応する C++ 型に置き換えられます。

繰り返し String フィールド

注: エディション 2023 以降では、features.(pb.cpp).string_typeVIEW に設定されている場合、代わりに string_view API が生成されます。

これらのフィールド定義のいずれか

repeated string foo = 1;
repeated bytes foo = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • int foo_size() const: フィールドに現在存在する要素の数を返します。空のセットを確認するには、このメソッドの代わりに、基になる RepeatedFieldempty() メソッドの使用を検討してください。
  • const string& foo(int index) const: 指定された 0 から始まるインデックスにある要素を返します。このメソッドを [0, foo_size()-1] の範囲外のインデックスで呼び出すと、未定義の動作になります。
  • void set_foo(int index, ::absl::string_view value): 指定された 0 から始まるインデックスにある要素の値を設定します。
  • void set_foo(int index, const string& value): 指定された 0 から始まるインデックスにある要素の値を設定します。
  • void set_foo(int index, string&& value): 指定された 0 から始まるインデックスにある要素の値を設定し、渡された文字列から移動します。
  • void set_foo(int index, const char* value): C スタイルの null 終端文字列を使用して、指定された 0 から始まるインデックスにある要素の値を設定します。
  • void set_foo(int index, const char* value, int size): null 終端バイトを探して決定するのではなく、明示的にサイズが指定された C スタイルの文字列を使用して、指定された 0 から始まるインデックスにある要素の値を設定します。
  • string* mutable_foo(int index): 指定された 0 から始まるインデックスにある要素の値を格納する可変 string オブジェクトへのポインタを返します。このメソッドを [0, foo_size()) の範囲外のインデックスで呼び出すと、未定義の動作になります。
  • void add_foo(::absl::string_view value): 指定された 0 から始まるインデックスにある要素の最後尾に新しい要素を追加します。
  • void add_foo(const string& value): 指定された値を持つ新しい要素をフィールドの最後に追加します。
  • void add_foo(string&& value): フィールドの最後尾に新しい要素を追加し、渡された文字列から移動します。
  • void add_foo(const char* value): C スタイルの null 終端文字列を使用して、フィールドの最後尾に新しい要素を追加します。
  • void add_foo(const char* value, int size): null 終端バイトを探して決定するのではなく、明示的にサイズが指定された文字列を使用して、フィールドの最後尾に新しい要素を追加します。
  • string* add_foo(): フィールドの最後尾に新しい空の文字列要素を追加し、そのポインタを返します。
  • void clear_foo(): フィールドからすべての要素を削除します。これを呼び出した後、foo_size() はゼロを返します。
  • const RepeatedPtrField<string>& foo() const: フィールドの要素を格納する基になる RepeatedPtrField を返します。このコンテナ クラスは、STL のようなイテレータやその他のメソッドを提供します。
  • RepeatedPtrField<string>* mutable_foo(): フィールドの要素を格納する基になる可変 RepeatedPtrField へのポインタを返します。このコンテナ クラスは、STL のようなイテレータやその他のメソッドを提供します。

繰り返し Enum フィールド

enum 型が与えられた場合

enum Bar {
  BAR_UNSPECIFIED = 0;
  BAR_VALUE = 1;
  BAR_OTHER_VALUE = 2;
}

このフィールド定義の場合

repeated Bar bar = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • int bar_size() const: フィールドに現在存在する要素の数を返します。空のセットを確認するには、このメソッドの代わりに、基になる RepeatedFieldempty() メソッドの使用を検討してください。
  • Bar bar(int index) const: 指定された 0 から始まるインデックスにある要素を返します。このメソッドを [0, bar_size()) の範囲外のインデックスで呼び出すと、未定義の動作になります。
  • void set_bar(int index, Bar value): 指定された 0 から始まるインデックスにある要素の値を設定します。デバッグ モード (つまり、NDEBUG が定義されていない場合) では、valueBar に定義された値のいずれとも一致しない場合、このメソッドはプロセスを中止します。
  • void add_bar(Bar value): 指定された値を持つ新しい要素をフィールドの最後に追加します。デバッグ モード (つまり、NDEBUG が定義されていない場合) では、valueBar に定義された値のいずれとも一致しない場合、このメソッドはプロセスを中止します。
  • void clear_bar(): フィールドからすべての要素を削除します。これを呼び出した後、bar_size() はゼロを返します。
  • const RepeatedField<int>& bar() const: フィールドの要素を格納する基になる RepeatedField を返します。このコンテナ クラスは、STL のようなイテレータやその他のメソッドを提供します。
  • RepeatedField<int>* mutable_bar(): フィールドの要素を格納する基になる可変 RepeatedField へのポインタを返します。このコンテナ クラスは、STL のようなイテレータやその他のメソッドを提供します。

繰り返し埋め込みメッセージ フィールド

メッセージ型が与えられた場合

message Bar {}

このフィールド定義の場合

repeated Bar bar = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • int bar_size() const: フィールドに現在存在する要素の数を返します。空のセットを確認するには、このメソッドの代わりに、基になる RepeatedFieldempty() メソッドの使用を検討してください。
  • const Bar& bar(int index) const: 指定された 0 から始まるインデックスにある要素を返します。このメソッドを [0, bar_size()) の範囲外のインデックスで呼び出すと、未定義の動作になります。
  • Bar* mutable_bar(int index): 指定された 0 から始まるインデックスにある要素の値を格納する可変 Bar オブジェクトへのポインタを返します。このメソッドを [0, bar_size()) の範囲外のインデックスで呼び出すと、未定義の動作になります。
  • Bar* add_bar(): フィールドの最後尾に新しい要素を追加し、そのポインタを返します。返される Bar は可変であり、フィールドは設定されていません (つまり、新しく割り当てられた Bar と同一になります)。
  • void clear_bar(): フィールドからすべての要素を削除します。これを呼び出した後、bar_size() はゼロを返します。
  • const RepeatedPtrField<Bar>& bar() const: フィールドの要素を格納する基になる RepeatedPtrField を返します。このコンテナ クラスは、STL のようなイテレータやその他のメソッドを提供します。
  • RepeatedPtrField<Bar>* mutable_bar(): フィールドの要素を格納する基になる可変 RepeatedPtrField へのポインタを返します。このコンテナ クラスは、STL のようなイテレータやその他のメソッドを提供します。

Oneof 数値フィールド

この oneof フィールド定義の場合

oneof example_name {
    int32 foo = 1;
    ...
}

コンパイラは、次のアクセサ メソッドを生成します。

  • bool has_foo() const: oneof ケースが kFoo の場合は true を返します。
  • int32 foo() const: oneof ケースが kFoo の場合はフィールドの現在の値を返します。それ以外の場合は、デフォルト値を返します。
  • void set_foo(int32 value):
    • 同じ oneof 内の他の oneof フィールドが設定されている場合は、clear_example_name() を呼び出します。
    • このフィールドの値を設定し、oneof case を kFoo に設定します。
    • has_foo() は true を返し、foo()value を返し、example_name_case()kFoo を返します。
  • void clear_foo():
    • oneof case が kFoo でない場合、何も変更されません。
    • oneof case が kFoo の場合、フィールドの値と oneof case をクリアします。has_foo()false を返し、foo() はデフォルト値を返し、example_name_case()EXAMPLE_NAME_NOT_SET を返します。

他の数値型フィールド(bool を含む)の場合、int32スカラー値型テーブル に従って対応する C++ 型に置き換えられます。

Oneof String フィールド

注: 2023 年版以降、string_view API が代わりに生成される場合があります。

これらの oneof フィールド定義のいずれかについて

oneof example_name {
    string foo = 1;
    ...
}
oneof example_name {
    bytes foo = 1;
    ...
}

コンパイラは、次のアクセサ メソッドを生成します。

  • bool has_foo() const: oneof case が kFoo の場合に true を返します。
  • const string& foo() const: oneof case が kFoo の場合、フィールドの現在の値を返します。それ以外の場合は、デフォルト値を返します。
  • void set_foo(::absl::string_view value):
    • 同じ oneof 内の他の oneof フィールドが設定されている場合は、clear_example_name() を呼び出します。
    • このフィールドの値を設定し、oneof case を kFoo に設定します。
    • has_foo()true を返し、foo()value のコピーを返し、example_name_case()kFoo を返します。
  • void set_foo(const string& value): 最初の set_foo() と同様ですが、const string 参照からコピーします。
  • void set_foo(string&& value): 最初の set_foo() と同様ですが、渡された文字列からムーブします。
  • void set_foo(const char* value): 最初の set_foo() と同様ですが、C スタイルのヌル終端文字列からコピーします。
  • void set_foo(const char* value, int size): 最初の set_foo() と同様ですが、ヌル終端バイトを探すのではなく、明示的に指定されたサイズを持つ文字列からコピーします。
  • string* mutable_foo():
    • 同じ oneof 内の他の oneof フィールドが設定されている場合は、clear_example_name() を呼び出します。
    • oneof case を kFoo に設定し、フィールドの値を格納するミュータブルな string オブジェクトへのポインタを返します。呼び出し前に oneof case が kFoo でなかった場合、返される文字列は空になります(デフォルト値ではありません)。
    • has_foo()true を返し、foo() は与えられた文字列に書き込まれた値を返し、example_name_case()kFoo を返します。
  • void clear_foo():
    • oneof case が kFoo でない場合、何も変更されません。
    • oneof case が kFoo の場合、フィールドを解放し、oneof case をクリアします。has_foo()false を返し、foo() はデフォルト値を返し、example_name_case()EXAMPLE_NAME_NOT_SET を返します。
  • void set_allocated_foo(string* value):
    • clear_example_name() を呼び出します。
    • string ポインタが NULL でない場合: string オブジェクトをフィールドに設定し、oneof case を kFoo に設定します。メッセージは割り当てられた string オブジェクトの所有権を取得し、has_foo()true を返し、example_name_case()kFoo を返します。
    • string ポインタが NULL の場合、has_foo()false を返し、example_name_case()EXAMPLE_NAME_NOT_SET を返します。
  • string* release_foo():
    • oneof case が kFoo でない場合、NULL を返します。
    • oneof case をクリアし、フィールドの所有権を解放し、string オブジェクトのポインタを返します。これを呼び出した後、呼び出し元は割り当てられた string オブジェクトの所有権を取得し、has_foo() は false を返し、foo() はデフォルト値を返し、example_name_case()EXAMPLE_NAME_NOT_SET を返します。

Oneof Enum フィールド

enum 型が与えられた場合

enum Bar {
  BAR_UNSPECIFIED = 0;
  BAR_VALUE = 1;
  BAR_OTHER_VALUE = 2;
}

oneof フィールド定義の場合

oneof example_name {
    Bar bar = 1;
    ...
}

コンパイラは、次のアクセサ メソッドを生成します。

  • bool has_bar() const: oneof case が kBar の場合に true を返します。
  • Bar bar() const: oneof case が kBar の場合、フィールドの現在の値を返します。それ以外の場合は、デフォルト値を返します。
  • void set_bar(Bar value):
    • 同じ oneof 内の他の oneof フィールドが設定されている場合は、clear_example_name() を呼び出します。
    • このフィールドの値を設定し、oneof case を kBar に設定します。
    • has_bar()true を返し、bar()value を返し、example_name_case()kBar を返します。
    • デバッグモード(つまり、NDEBUG が定義されていない場合)で、valueBar に定義された値のいずれにも一致しない場合、このメソッドはプロセスを中止します。
  • void clear_bar():
    • oneof case が kBar でない場合、何も変更されません。
    • oneof case が kBar の場合、フィールドの値と oneof case をクリアします。has_bar()false を返し、bar() はデフォルト値を返し、example_name_case()EXAMPLE_NAME_NOT_SET を返します。

Oneof 埋め込みメッセージ フィールド

メッセージ型が与えられた場合

message Bar {}

oneof フィールド定義の場合

oneof example_name {
    Bar bar = 1;
    ...
}

コンパイラは、次のアクセサ メソッドを生成します。

  • bool has_bar() const: oneof case が kBar の場合に true を返します。
  • const Bar& bar() const: oneof case が kBar の場合、フィールドの現在の値を返します。それ以外の場合は、フィールドが設定されていない Bar(おそらく Bar::default_instance())を返します。
  • Bar* mutable_bar():
    • 同じ oneof 内の他の oneof フィールドが設定されている場合は、clear_example_name() を呼び出します。
    • oneof case を kBar に設定し、フィールドの値を格納するミュータブルな Bar オブジェクトへのポインタを返します。呼び出し前に oneof case が kBar でなかった場合、返される Bar はフィールドが設定されていません(つまり、新しく割り当てられた Bar と同じになります)。
    • これを呼び出した後、has_bar()true を返し、bar()Bar の同じインスタンスへの参照を返し、example_name_case()kBar を返します。
  • void clear_bar():
    • oneof case が kBar でない場合、何も変更されません。
    • oneof case が kBar と等しい場合、フィールドを解放し、oneof case をクリアします。has_bar()false を返し、bar() はデフォルト値を返し、example_name_case()EXAMPLE_NAME_NOT_SET を返します。
  • void set_allocated_bar(Bar* bar):
    • clear_example_name() を呼び出します。
    • Bar ポインタが NULL でない場合: Bar オブジェクトをフィールドに設定し、oneof case を kBar に設定します。メッセージは割り当てられた Bar オブジェクトの所有権を取得し、has_bar() は true を返し、example_name_case()kBar を返します。
    • ポインタが NULL の場合、has_bar()false を返し、example_name_case()EXAMPLE_NAME_NOT_SET を返します。(動作は clear_example_name() の呼び出しに似ています)
  • Bar* release_bar():
    • oneof case が kBar でない場合、NULL を返します。
    • oneof case が kBar の場合、oneof case をクリアし、フィールドの所有権を解放し、Bar オブジェクトのポインタを返します。これを呼び出した後、呼び出し元は割り当てられた Bar オブジェクトの所有権を取得し、has_bar()false を返し、bar() はデフォルト値を返し、example_name_case()EXAMPLE_NAME_NOT_SET を返します。

Map フィールド

この map フィールド定義の場合

map<int32, int32> weight = 1;

コンパイラは、次のアクセサ メソッドを生成します。

  • const google::protobuf::Map<int32, int32>& weight();: イミュータブルな Map を返します。
  • google::protobuf::Map<int32, int32>* mutable_weight();: ミュータブルな Map を返します。

google::protobuf::Map は、プロトコルバッファで map フィールドを格納するために使用される特別なコンテナ型です。以下のインターフェースからわかるように、std::map および std::unordered_map メソッドの一般的に使用されるサブセットを使用しています。

template<typename Key, typename T> {
class Map {
  // Member types
  typedef Key key_type;
  typedef T mapped_type;
  typedef MapPair< Key, T > value_type;

  // Iterators
  iterator begin();
  const_iterator begin() const;
  const_iterator cbegin() const;
  iterator end();
  const_iterator end() const;
  const_iterator cend() const;
  // Capacity
  int size() const;
  bool empty() const;

  // Element access
  T& operator[](const Key& key);
  const T& at(const Key& key) const;
  T& at(const Key& key);

  // Lookup
  bool contains(const Key& key) const;
  int count(const Key& key) const;
  const_iterator find(const Key& key) const;
  iterator find(const Key& key);

  // Modifiers
  pair<iterator, bool> insert(const value_type& value);
  template<class InputIt>
  void insert(InputIt first, InputIt last);
  size_type erase(const Key& Key);
  iterator erase(const_iterator pos);
  iterator erase(const_iterator first, const_iterator last);
  void clear();

  // Copy
  Map(const Map& other);
  Map& operator=(const Map& other);
}

データを追加する最も簡単な方法は、通常の map 構文を使用することです。たとえば

std::unique_ptr<ProtoName> my_enclosing_proto(new ProtoName);
(*my_enclosing_proto->mutable_weight())[my_key] = my_value;

pair<iterator, bool> insert(const value_type& value) は、value_type インスタンスのディープコピーを暗黙的に引き起こします。google::protobuf::Map に新しい値を挿入する最も効率的な方法は、次のとおりです

T& operator[](const Key& key): map[new_key] = new_mapped;

標準 map での google::protobuf::Map の使用

google::protobuf::Map は、std::map および std::unordered_map と同じイテレータ API をサポートしています。google::protobuf::Map を直接使用したくない場合は、次のようにして google::protobuf::Map を標準 map に変換できます

std::map<int32, int32> standard_map(message.weight().begin(),
                                    message.weight().end());

これにより、map 全体のディープコピーが作成されることに注意してください。

次のようにして、標準 map から google::protobuf::Map を構築することもできます

google::protobuf::Map<int32, int32> weight(standard_map.begin(), standard_map.end());

不明な値の解析

ワイヤ上では、.proto map はキー/値ペアごとに map エントリメッセージと同等ですが、map 自体は map エントリの繰り返しフィールドです。通常のメッセージ型と同様に、解析された map エントリメッセージに不明なフィールドが含まれている可能性があります。たとえば、map<int32, string> として定義された map 内の int64 型のフィールドなどです。

map エントリメッセージのワイヤ形式に不明なフィールドがある場合、それらは破棄されます。

map エントリメッセージのワイヤ形式に不明な enum 値がある場合、proto2 と proto3 で処理が異なります。proto2 では、map エントリメッセージ全体が、包含メッセージの不明なフィールドセットに入れられます。proto3 では、既知の enum 値であるかのように map フィールドに入れられます。

Any

次のような Any フィールドが与えられた場合

import "google/protobuf/any.proto";

message ErrorStatus {
  string message = 1;
  google.protobuf.Any details = 2;
}

生成されたコードでは、details フィールドのゲッターは google::protobuf::Any のインスタンスを返します。これにより、Any の値をパックおよびアンパックするための次の特別なメソッドが提供されます

class Any {
 public:
  // Packs the given message into this Any using the default type URL
  // prefix “type.googleapis.com”. Returns false if serializing the message failed.
  bool PackFrom(const google::protobuf::Message& message);

  // Packs the given message into this Any using the given type URL
  // prefix. Returns false if serializing the message failed.
  bool PackFrom(const google::protobuf::Message& message,
                ::absl::string_view type_url_prefix);

  // Unpacks this Any to a Message. Returns false if this Any
  // represents a different protobuf type or parsing fails.
  bool UnpackTo(google::protobuf::Message* message) const;

  // Returns true if this Any represents the given protobuf type.
  template<typename T> bool Is() const;
}

Oneof

次のような oneof 定義が与えられた場合

oneof example_name {
    int32 foo_int = 4;
    string foo_string = 9;
    ...
}

コンパイラは、次の C++ enum 型を生成します

enum ExampleNameCase {
  kFooInt = 4,
  kFooString = 9,
  EXAMPLE_NAME_NOT_SET = 0
}

さらに、次のメソッドを生成します

  • ExampleNameCase example_name_case() const: どのフィールドが設定されているかを示す enum を返します。どれも設定されていない場合は EXAMPLE_NAME_NOT_SET を返します。
  • void clear_example_name(): oneof フィールドセットがポインタ(Message または String)を使用している場合、オブジェクトを解放し、oneof case を EXAMPLE_NAME_NOT_SET に設定します。

列挙型

注: 2024 年版以降、特定の機能設定で string_view API が生成される場合があります。このトピックの詳細については、列挙型名ヘルパー を参照してください。

次のような enum 定義が与えられた場合

enum Foo {
  VALUE_A = 0;
  VALUE_B = 5;
  VALUE_C = 1234;
}

プロトコルバッファコンパイラは、同じ値セットを持つ Foo という名前の C++ enum 型を生成します。さらに、コンパイラは次の関数を生成します

  • const EnumDescriptor* Foo_descriptor(): この enum 型が定義する値に関する情報を含む、型の記述子を返します。
  • bool Foo_IsValid(int value): 指定された数値が Foo の定義済み値のいずれかに一致する場合、true を返します。上記の例では、入力が 0、5、または 1234 の場合に true を返します。
  • const string& Foo_Name(int value): 指定された数値の名前を返します。そのような値が存在しない場合は、空の文字列を返します。複数の値がこの数値を持つ場合、最初に定義された値が返されます。上記の例では、Foo_Name(5)"VALUE_B" を返します。
  • bool Foo_Parse(::absl::string_view name, Foo* value): name がこの enum の有効な値名である場合、その値を value に代入し、true を返します。それ以外の場合は false を返します。上記の例では、Foo_Parse("VALUE_C", &some_foo) は true を返し、some_foo を 1234 に設定します。
  • const Foo Foo_MIN: enum の最小有効値(例では VALUE_A)。
  • const Foo Foo_MAX: enum の最大有効値(例では VALUE_C)。
  • const int Foo_ARRAYSIZE: 常に Foo_MAX + 1 として定義されます。

整数を proto2 enum にキャストする場合は注意してください。整数が proto2 enum 値にキャストされる場合、整数は、その enum の有効な値のいずれかでなければなりません。そうでない場合、結果は未定義になる可能性があります。疑問がある場合は、生成された Foo_IsValid() 関数を使用して、キャストが有効かどうかをテストしてください。proto2 メッセージの enum 型フィールドを無効な値に設定すると、アサーションエラーが発生する可能性があります。proto2 メッセージの解析時に無効な enum 値が読み取られると、不明なフィールド として扱われます。これらのセマンティクスは proto3 で変更されました。int32 に収まる限り、任意の整数を proto3 enum 値にキャストしても安全です。proto3 メッセージの解析時に無効な enum 値も保持され、enum フィールドアクセサーによって返されます。

switch ステートメントで proto3 enum を使用する場合は注意してください。Proto3 enum は、指定されたシンボルの範囲外の可能な値を持つオープン enum 型です。認識されない enum 値は、proto3 メッセージの解析時に保持され、enum フィールドアクセサーによって返されます。既知のフィールドがすべてリストされている場合でも、デフォルトケースのない proto3 enum の switch ステートメントは、すべてのケースをキャッチできるとは限りません。これにより、データの破損やランタイムクラッシュなどの予期しない動作が発生する可能性があります。常にデフォルトケースを追加するか、switch の外部で明示的に Foo_IsValid(int) を呼び出して、不明な enum 値を処理してください。

メッセージ型内で enum を定義できます。この場合、プロトコルバッファコンパイラは、enum 型自体がメッセージのクラス内にネストされて宣言されているように見えるコードを生成します。Foo_descriptor() 関数と Foo_IsValid() 関数は、静的メソッドとして宣言されます。実際には、enum 型自体とその値は、マングルされた名前でグローバルスコープで宣言され、typedef と一連の定数定義を使用してクラスのスコープにインポートされます。これは、宣言順序に関する問題を回避するためだけに行われます。マングルされたトップレベルの名前には依存しないでください。enum が実際にメッセージクラスにネストされていると見なしてください。

拡張機能 (proto2 のみ)

拡張範囲を持つメッセージが与えられた場合

message Foo {
  extensions 100 to 199;
}

プロトコルバッファコンパイラは、Foo 用に追加のメソッドを生成します。HasExtension()ExtensionSize()ClearExtension()GetExtension()SetExtension()MutableExtension()AddExtension()SetAllocatedExtension()ReleaseExtension() です。これらの各メソッドは、最初のパラメータとして、拡張フィールドを識別する拡張識別子(下記で説明)を取ります。残りのパラメータと戻り値は、拡張識別子と同じ型の通常の(非拡張)フィールドに対して生成されるアクセスメソッドに対応するものとまったく同じです。(GetExtension() は、特別なプレフィックスのないアクセサーに対応します。)

拡張定義が与えられた場合

extend Foo {
  optional int32 bar = 123;
  repeated int32 repeated_bar = 124;
  optional Bar message_bar = 125;
}

単数拡張フィールド bar の場合、プロトコルバッファコンパイラは、この拡張機能にアクセスするために Foo の拡張アクセサーで使用できる bar という名前の「拡張識別子」を生成します。次に例を示します

Foo foo;
assert(!foo.HasExtension(bar));
foo.SetExtension(bar, 1);
assert(foo.HasExtension(bar));
assert(foo.GetExtension(bar) == 1);
foo.ClearExtension(bar);
assert(!foo.HasExtension(bar));

メッセージ拡張フィールド message_bar の場合、フィールドが設定されていない場合、foo.GetExtension(message_bar) は、フィールドが設定されていない Bar(おそらく Bar::default_instance())を返します。

同様に、繰り返し拡張フィールド repeated_bar の場合、コンパイラは repeated_bar という名前の拡張識別子を生成します。これも Foo の拡張アクセサーで使用できます

Foo foo;
for (int i = 0; i < kSize; ++i) {
  foo.AddExtension(repeated_bar, i)
}
assert(foo.ExtensionSize(repeated_bar) == kSize)
for (int i = 0; i < kSize; ++i) {
  assert(foo.GetExtension(repeated_bar, i) == i)
}

(拡張識別子の正確な実装は複雑で、テンプレートの魔法のような使用が含まれますが、拡張識別子を使用するためにその仕組みについて心配する必要はありません。)

拡張機能は、別の型の中にネストして宣言できます。たとえば、一般的なパターンは、次のようなことを行うことです

message Baz {
  extend Foo {
    optional Baz foo_ext = 124;
  }
}

この場合、拡張識別子 foo_extBaz の内部にネストして宣言されます。次のように使用できます

Foo foo;
Baz* baz = foo.MutableExtension(Baz::foo_ext);
FillInMyBaz(baz);

Arena アロケーション

アリーナ割り当ては、プロトコルバッファを扱う際のメモリ使用量を最適化し、パフォーマンスを向上させるのに役立つ C++ のみの機能です。.proto でアリーナ割り当てを有効にすると、アリーナを扱うための追加コードが C++ 生成コードに追加されます。アリーナ割り当て API の詳細については、アリーナ割り当てガイド を参照してください。

サービス

.proto ファイルに次の行が含まれている場合

option cc_generic_services = true;

次に、プロトコルバッファコンパイラは、このセクションで説明されているように、ファイルで見つかったサービス定義に基づいてコードを生成します。ただし、生成されたコードは、特定の RPC システムに関連付けられていないため、望ましくない場合があります。したがって、1 つのシステムに合わせたコードよりも多くのレベルの間接参照が必要です。このコードを生成したくない場合は、次の行をファイルに追加します

option cc_generic_services = false;

上記の行のいずれも指定されていない場合、オプションはデフォルトで false になります。これは、汎用サービスが非推奨になったためです。(2.4.0 より前のバージョンでは、オプションはデフォルトで true であったことに注意してください)

.proto 言語サービス定義に基づく RPC システムは、システムに適したコードを生成するための プラグイン を提供する必要があります。これらのプラグインは、抽象サービスを無効にして、同じ名前の独自のクラスを生成できるようにする必要がある可能性があります。

このセクションの残りの部分では、抽象サービスが有効になっている場合にプロトコルバッファコンパイラが生成する内容について説明します。

インターフェース

サービス定義が与えられた場合

service Foo {
  rpc Bar(FooRequest) returns(FooResponse);
}

プロトコルバッファコンパイラは、このサービスを表すクラス Foo を生成します。Foo には、サービス定義で定義された各メソッドの仮想メソッドがあります。この場合、メソッド Bar は次のように定義されています

virtual void Bar(RpcController* controller, const FooRequest* request,
                 FooResponse* response, Closure* done);

パラメータは、method 引数が暗黙的であり、request および response が正確な型を指定することを除いて、Service::CallMethod() のパラメータと同等です。

これらの生成されたメソッドは仮想ですが、純粋仮想ではありません。デフォルトの実装は、メソッドが実装されていないことを示すエラーメッセージで controller->SetFailed() を呼び出し、次に done コールバックを呼び出すだけです。独自のサービスを実装する場合は、この生成されたサービスをサブクラス化し、そのメソッドを適切に実装する必要があります。

FooService インターフェースをサブクラス化します。プロトコルバッファコンパイラは、次のように Service のメソッドの実装を自動的に生成します

  • GetDescriptor: サービスの ServiceDescriptor を返します。
  • CallMethod: 提供されたメソッド記述子に基づいて呼び出されているメソッドを決定し、リクエストおよびレスポンスメッセージオブジェクトを正しい型にダウンキャストして、直接呼び出します。
  • GetRequestPrototype および GetResponsePrototype: 指定されたメソッドの正しい型のリクエストまたはレスポンスのデフォルトインスタンスを返します。

次の静的メソッドも生成されます

  • static ServiceDescriptor descriptor(): このサービスが持つメソッドとその入力型と出力型に関する情報を含む、型の記述子を返します。

スタブ

プロトコルバッファコンパイラは、すべてのサービスインターフェースの「スタブ」実装も生成します。これは、サービスを実装するサーバーにリクエストを送信したいクライアントによって使用されます。Foo サービス(上記)の場合、スタブ実装 Foo_Stub が定義されます。ネストされたメッセージ型と同様に、Foo_StubFoo::Stub とも呼べるように、typedef が使用されます。

Foo_StubFoo のサブクラスであり、次のメソッドも実装します

  • Foo_Stub(RpcChannel* channel): 指定されたチャネルでリクエストを送信する新しいスタブを構築します。
  • Foo_Stub(RpcChannel* channel, ChannelOwnership ownership): 指定されたチャネルでリクエストを送信し、そのチャネルを所有する可能性のある新しいスタブを構築します。ownershipService::STUB_OWNS_CHANNEL の場合、スタブオブジェクトが削除されると、チャネルも削除されます。
  • RpcChannel* channel(): コンストラクタに渡された、このスタブのチャネルを返します。

スタブは、サービスの各メソッドをチャネルのラッパーとして追加で実装します。メソッドの 1 つを呼び出すと、単に channel->CallMethod() を呼び出します。

Protocol Buffer ライブラリには、RPC 実装は含まれていません。ただし、生成されたサービスクラスを任意の RPC 実装に接続するために必要なすべてのツールが含まれています。RpcChannel および RpcController の実装を提供するだけで済みます。詳細については、service.h のドキュメントを参照してください。

プラグイン挿入ポイント

コードジェネレータプラグイン は、C++ コードジェネレータの出力を拡張したい場合、指定された挿入ポイント名を使用して、次のタイプのコードを挿入できます。各挿入ポイントは、特に明記されていない限り、.pb.cc ファイルと .pb.h ファイルの両方に表示されます。

  • includes: インクルードディレクティブ。
  • namespace_scope: ファイルのパッケージ/名前空間に属する宣言ですが、特定のクラス内には属しません。他のすべての名前空間スコープコードの後に表示されます。
  • global_scope: ファイルの名前空間の外側のトップレベルに属する宣言。ファイルの最後に表示されます。
  • class_scope:TYPENAME: メッセージクラスに属するメンバー宣言。TYPENAME は完全な proto 名です。たとえば、package.MessageType などです。クラス内の他のすべての public 宣言の後に表示されます。この挿入ポイントは .pb.h ファイルにのみ表示されます。

標準コードジェネレータによって宣言されたプライベートクラスメンバーに依存するコードを生成しないでください。これらの実装の詳細は、Protocol Buffers の将来のバージョンで変更される可能性があります。