protoc-gen-grpcxx
can be used to translate gRPC service definitions from .proto
files to C++ code.
Let's take the following proto definitions from helloworld example.
syntax = "proto3";
package helloworld.v1;
service Greeter {
rpc Hello(GreeterHelloRequest) returns (GreeterHelloResponse) {}
}
message GreeterHelloRequest {
string name = 1;
}
message GreeterHelloResponse {
string message = 1;
}
Using protoc
and protoc-gen-grpcxx
, we can generate the grpcxx::service
definitions and stub implementations.
e.g.
❯ protoc --proto_path=. \
--cpp_out=/path/to/output \
--grpcxx_out=/path/to/output \
--plugin=/path/to/protoc-gen-grpcxx \
helloworld/v1/greeter.proto
The above command will output 3 files.
❯ tree /path/to/output
/path/to/output
└── helloworld
└── v1
├── greeter.grpcxx.pb.h
├── greeter.pb.cc
└── greeter.pb.h
greeter.pb.h
and greeter.pb.cc
contains the C++ definitions and implementations for protobuf messages.
greeter.grpcxx.pb.h
containes the grpcxx::service
definitions and stub implementations.
greeter.grpcxx.pb.h
would look something like this;
// Code generated by protoc-gen-grpcxx.
// Versions:
// - protoc-gen-grpcxx: v0.1.0
// Source: helloworld/v1/greeter.proto
#pragma once
#include <grpcxx/rpc.h>
#include <grpcxx/service.h>
#include "helloworld/v1/greeter.pb.h"
namespace helloworld {
namespace v1 {
namespace Greeter {
using rpcHello = grpcxx::rpc<"Hello", GreeterHelloRequest, GreeterHelloResponse>;
using Service = grpcxx::service<"helloworld.v1.Greeter", rpcHello>;
struct ServiceImpl {
template <typename T>
typename T::result_type call(grpcxx::context &, const typename T::request_type &) {
return {grpcxx::status::code_t::unimplemented, std::nullopt};
}
};
} // namespace Greeter
} // namespace v1
} // namespace helloworld
While you could manually invoke protoc
and protoc-gen-grpcxx
to generate code, you could also generate the code as part of your project build process.
Here's a snippet that uses CMake's add_custom_command to generate code as part of the build.
add_custom_command(
OUTPUT ${headers} ${sources}
DEPENDS ${protos}
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
ARGS
--proto_path=${CMAKE_CURRENT_SOURCE_DIR}
--proto_path=${Protobuf_INCLUDE_DIR}
--cpp_out=${CMAKE_CURRENT_BINARY_DIR}
--grpcxx_out=${CMAKE_CURRENT_BINARY_DIR}
--plugin=protoc-gen-grpcxx=$<TARGET_FILE:libgrpcxx::protoc-gen>
${protos}
)
💡 You can find a complete example here.