【问题标题】:C RPC without the stubs没有存根的 C RPC
【发布时间】:2010-10-18 11:56:49
【问题描述】:

我有这个程序,我希望其他进程能够调用函数(通过 unix 套接字)。消息协议很简单,函数名,函数签名,和保存参数的缓冲区(char *)。

当我的程序中的一个模块想要允许访问某个函数时,它会在库中注册名称和签名。我面临的问题是一旦请求进入就物理调用该函数。我查看了 RPC 和 java RMI 类库,但这些库需要我生成存根来包装调用。我正在开发的系统非常动态,我还必须与我无法修改的其他人的代码交互。

所以基本上,一个函数可能看起来像:

int somefunc(int someparam, double another)
{
    return 1234;
}

现在我在图书馆注册:

//           func ptr   name       signature
REG_FUNCTION(somefunc, "somefunc", "i:id");

当请求进来时,我会做一些错误检查,一旦有效我想调用该函数。所以我有变量:

void * funcptr = (the requested function);
char * sig = (the function signature);
char * params = (a buffer of function parameters);
//note that the params buffer can hold data types of arbitrary lengths

如何在 C 中调用带有参数的函数?

谢谢!

【问题讨论】:

  • 你需要签名做什么?客户端是调用函数还是将请求传递给包含 somefunc 的库?一些澄清会有所帮助!

标签: c rpc


【解决方案1】:

我认为这通常不能完全解决,仅使用 C。例如,您不知道目标函数使用的调用约定。您最终可能会“欺骗”编译器,或者至少不得不对其进行猜测。如果编译器决定使用在寄存器中传递的参数来构建注册函数怎么办,可能是由于一些优化设置(或者如果它是用不同的编译器构建的呢?)。

通常也没有办法在 C 中表示您要调用具有给定参数集的函数,并且参数的值需要从随机字节的缓冲区中解压缩。

你可以做这样可怕的事情:

enum { VOID_INT, VOID_INT_DOUBLE, VOID_DOUBLE_INT, ... } Signature;

void do_call(const void *userfunction, const void *args, Signature sig)
{
  switch(signature)
  {
    case VOID_INT:
    {
      int x = *(int *) args;
      void (*f)(int) = userfunction;
      f(x);
      break;
    }
    case VOID_INT_DOUBLE:
    ...
  }
}

但很明显,这与可扩展性不同。您当然可以为一些合理的返回类型和参数类型自动生成此代码。将函数指针转换为void * 或从void * 转换函数指针时,您仍然会感到有些冷漠,但这可能是可以接受的。但是,您仍然总是冒着有人将签名交给您的风险,而您没有预先生成的代码。

【讨论】:

    【解决方案2】:

    查看libffi。该库允许使用在运行时指定的一组参数调用函数。

    【讨论】:

      猜你喜欢
      • 2021-11-06
      • 1970-01-01
      • 1970-01-01
      • 2013-07-01
      • 2018-01-05
      • 2021-12-04
      • 2013-08-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多