Есть задумка и реализация RPC который не использует прекомпилированые IDL (или protobuf) и не использует специфичные прототипы для функций (условные
RPC_ERR (*func) (rpc_arg** args, rpc_arg* ret);
).
Вместо этого он использует libffi и вызывает функцию через указатель и генерирует массив аргументов для функции по "описанию" (enum массив описывающий типы) и аргументам от клиента. Если кому нужно
исходники тут .
Пример простого сервера:
int test(char* a, int b){
printf("%s:%d\n",a,b);
return -b;
}
int main(){
struct rpcserver* serv = rpcserver_create(1234); //создаем сервер на 1234 порту
enum rpctypes proto[] = {STR,INT32}; //это то самое описание функции
rpcserver_load_keys(serv,"keys"); //загружка "ключей" (пара пароль-привелегия "key"0 )
int minperm = -1; //минимальные привелегии для вызова функции
rpcserver_register_fn(serv,test,"test",INT32,proto,sizeof(proto) / sizeof(proto[0]),NULL,minperm);
rpcserver_start(serv);
getchar();
rpcserver_free(serv);
}
API вызова функции с клиента использует variable arguments, так-же можно пересылать некоторые типы аргументов обратно на клиент( (char*, uint64_t (SIZEDBUF) ), rpcbuff, rpcstruct). rpcbuff реализовывает многомерный массив а rpcstruct это просто хештаблица с автоматической упаковкой и распаковкой типов, по факту ее можно использовать и как ассоциативный массив, структуру, связанный список
int main(int argc, char** argv){
if(argc < 5 || argc > 5){
puts("WRONG usage: ./name [server ip] [port] [key] [msg]");
return 1;
}
char* serv_domain = argv[1];
int port = atoi(argv[2]);
char* key = argv[3];
struct rpccon con = {0};
assert(rpcserver_connect(serv_domain,key,port,&con) == 0);
enum rpctypes proto[] = {STR,INT32};
int32_t ret = 0;
rpcclient_call(&con,"test",proto,NULL,sizeof(proto) / sizeof(proto[0]),&ret,argv[4],52);
printf("%d:ret\n",ret);
rpcclient_discon(&con);
}
Что думаете это жизнеспособный проект / задумка или стоит от нее отказаться?