I have been playing around lately with `GRPC` and `Protocol Buffers` in order to get familiar with both frameworks in C++.
I wanted to experiment with the reflection functionality, so I have set up a very simple service where the (reflection-enabled) server exposes the following interface file:
syntax = "proto3";
package helloworld;
service Server {
rpc Add (AddRequest) returns (AddReply) {}
}
message AddRequest {
int32 arg1 = 1;
int32 arg2 = 2;
}
message AddReply {
int32 sum = 1;
}
On the client side I have visibility of the previous method thanks to the `grpc::ProtoReflectionDescriptorDatabase`. Therefore, I am able to create a message by means of a `DynamicMessageFactory`. However, I haven't been able to actually send the message to the server, nor, find any specific details in the documentation. Maybe it's too obvious and I'm completely lost...
Any hints will be deeply appreciated!
using namespace google::protobuf;
void demo()
{
std::shared_ptr<grpc::Channel> channel = grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials());
// Inspect exposed method
grpc::ProtoReflectionDescriptorDatabase reflection_database(channel);
std::vector<std::string> output;
reflection_database.GetServices(&output);
DescriptorPool reflection_database_pool(&reflection_database);
const ServiceDescriptor* service = reflection_database_pool.FindServiceByName(output[0]);
const MethodDescriptor* method = service->method(0);
// Create request message
const Descriptor* input_descriptor = method->input_type();
FileDescriptorProto input_proto;
input_descriptor->file()->CopyTo(&input_proto);
DescriptorPool pool;
const FileDescriptor* input_file_descriptor = pool.BuildFile(input_proto);
const Descriptor* input_message_descriptor = input_file_descriptor->FindMessageTypeByName(input_descriptor->name());
DynamicMessageFactory factory;
Message* request = factory.GetPrototype(input_message_descriptor)->New();
// Fill request message (sum 1 plus 2)
const Reflection* reflection = request->GetReflection();
const FieldDescriptor* field1 = input_descriptor->field(0);
reflection->SetInt32(request, field1, 1);
const FieldDescriptor* field2 = input_descriptor->field(1);
reflection->SetInt32(request, field2, 2);
// Create response message
const Descriptor* output_descriptor = method->output_type();
FileDescriptorProto output_proto;
output_descriptor->file()->CopyTo(&output_proto);
const FileDescriptor* output_file_descriptor = pool.BuildFile(output_proto);
const Descriptor* output_message_descriptor = output_file_descriptor->FindMessageTypeByName(output_descriptor->name());
Message* response = factory.GetPrototype(output_message_descriptor)->New();
// How to create a call...?
// ...is grpc::BlockingUnaryCall the way to proceed?
}