我有一个用 C 编写的程序,想在其中包含 gRPC。然而,gRPC 的 API 是用 C++ 编写的。
我查看了这里并让 foo_client 和 foo_server 正常工作。 https://github.com/Juniper/grpc-c/tree/master/examples
但是,C 客户端与我的 gRPC C++ 服务器不兼容。他们不会互相交谈。我相信这是因为我使用的是最新的 gRPC,它使用 protocbuf 版本 3.2.0。 Juniper 的 grpc-c 使用的是旧版本的 gRPC,该版本使用 protocbuf 版本 3.0.0。
因此,C 语言的 Juniper 版本似乎不适用于新的 gRPC。我知道 gRPC 低级 C API 应该在这里:https://github.com/grpc/grpc/blob/master/include/grpc/grpc.h 但我在实施它时遇到了困难。谁能帮我理解一下吗?
我有一段时间没有用 C 编程了,所以我有点生疏了。
如果您直接使用 gRPC 核心库,那么您将需要执行自己的序列化,并处理https://github.com/grpc/grpc/blob/master/include/grpc/ 中记录的低级操作impl/codegen/grpc_types.h.
如果您有任何具体问题,我们很乐意为您提供帮助,但如果这只是一次性的事情,那么解决版本不兼容问题可能会更容易,或者简单地用 C 接口包装 C++ 实现。
有几种方法可以解决这个问题:
有一个用 C 编写的
EZgRPC
服务器,但有一些限制,例如:
摘自
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;
}