我有这个程序,我希望其他进程能够调用函数(通过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?
中的参数调用该函数谢谢!
答案 0 :(得分:2)
我不认为这通常是完全可解的,只使用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 *
转换函数指针,你仍然有点冷,但这可能是可以接受的。但是,你仍然总是冒着有人给你签名的风险,你没有预先生成的代码。
答案 1 :(得分:0)
结帐libffi。该库允许使用在运行时指定的一组参数来调用函数。