Reputation: 101
I have a program written in C and want to include gRPC in it. However, the API for gRPC is written in C++.
I've looked here and got the foo_client and foo_server working. https://github.com/Juniper/grpc-c/tree/master/examples
However, the C client is not compatible with my gRPC C++ server. They will not talk to each other. I believe it is because I am using the lates gRPC which uses protocbuf version 3.2.0. And Juniper's grpc-c is using an older version of gRPC that uses protocbuf version 3.0.0.
So the Juniper version in C doesn't seem to work with the new gRPC. I know the gRPC low level C API is supposed to be here: https://github.com/grpc/grpc/blob/master/include/grpc/grpc.h But I'm having difficulty implementing it. Can anyone help me make sense of it?
I haven't programmed in C in awhile so I'm a little rusty.
Upvotes: 9
Views: 14607
Reputation: 109
There's an EZgRPC
server written in C, but there's some limitations, like:
EZgRPC: https://github.com/mnyoshie/ezgrpc
Taken from hello_world_server.c
:
/* the author disclaims copyright to this example source code
* and releases it into the public domain
*/
#include "ezgrpc.h"
int whatever_service1(ezgrpc_message_t *req, ezgrpc_message_t **res, void *userdata){
ezgrpc_message_t *msg = calloc(1, sizeof(ezgrpc_message_t));
printf("called service1. received %u bytes\n", req->data_len);
msg->is_compressed = 0;
msg->data_len = 3;
msg->data = malloc(3);
/* protobuf serialized message */
msg->data[0] = 0x08;
msg->data[1] = 0x96;
msg->data[2] = 0x02;
msg->next = NULL;
*res = msg;
//sleep(2);
return 0;
}
int another_service2(ezgrpc_message_t *req, ezgrpc_message_t **res, void *userdata){
printf("called service2\n");
return 0;
}
int main(){
int pfd[2];
if (pipe(pfd))
assert(0);
sigset_t sig_mask;
ezhandler_arg ezarg = {&sig_mask, pfd[1]};
if (ezgrpc_init(ezserver_signal_handler, &ezarg)) {
fprintf(stderr, "fatal: couldn't init ezgrpc\n");
return 1;
}
EZGRPCServer *server_handle = ezgrpc_server_init();
assert(server_handle != NULL);
ezgrpc_server_add_service(server_handle, "/test.yourAPI/whatever_service1", whatever_service1, NULL, NULL, 0);
ezgrpc_server_add_service(server_handle, "/test.yourAPI/another_service2", another_service2, NULL, NULL, 0);
ezgrpc_server_set_ipv4_bind_addr(server_handle, "0.0.0.0");
ezgrpc_server_set_ipv4_bind_port(server_handle, 19009);
ezgrpc_server_set_ipv6_bind_addr(server_handle, "::");
ezgrpc_server_set_ipv6_bind_port(server_handle, 19009);
ezgrpc_server_set_shutdownfd(server_handle, pfd[0]);
/* This call is blocking.
* when a SIGINT/SIGTERM is received, it should return */
ezgrpc_server_start(server_handle);
ezgrpc_server_free(server_handle);
return 0;
}
Upvotes: 0
Reputation: 799
There are a few ways to approach this:
Upvotes: 1
Reputation: 437
If you are using the gRPC core library directly, then you will need to perform your own serialization, and deal with low level operations documented in https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/grpc_types.h.
If you have any specific questions, we will be happy to help, but if this is just a one-time thing it might be easier to just solve the version incompatibility problem, or maybe simply wrap the C++ implementation with a C interface.
Upvotes: 5