我正在尝试做类似以下的事情
enum types {None, Bool, Short, Char, Integer, Double, Long, Ptr};
int main(int argc, char ** args) {
enum types params[10] = {0};
void* triangle = dlopen("./foo.so", RTLD_LAZY);
void * fun = dlsym(triangle, ars[1]);
<<pseudo code>>
}
伪代码类似于
fun = {}
for param in params:
if param == None:
fun += void
if param == Bool:
fun += Boolean
if param == Integer:
fun += int
...
returnVal = fun.pop()
funSignature = returnval + " " + funName + "(" + Riffle(fun, ",") + ")"
exec funSignature
谢谢
事实上,你几乎可以做任何你想做的事。在 C 语言中(例如,与 C++ 不同),共享对象中的函数仅通过其名称来引用。所以,找到——而且,最重要的是,call--正确的函数,你不需要它的完整签名。你只需要它的名字!这既是优点也是缺点——但这就是您选择的语言的本质。
让我演示一下它是如何工作的。
#include <dlfcn.h>
typedef void* (*arbitrary)();
// do not mix this with typedef void* (*arbitrary)(void); !!!
int main()
{
arbitrary my_function;
// Introduce already loaded functions to runtime linker's space
void* handle = dlopen(0,RTLD_NOW|RTLD_GLOBAL);
// Load the function to our pointer, which doesn't know how many arguments there sould be
*(void**)(&my_function) = dlsym(handle,"something");
// Call something via my_function
(void) my_function("I accept a string and an integer!\n",(int)(2*2));
return 0;
}
事实上,您可以通过这种方式调用任何函数。然而,有一个缺点。你其实需要在编译时知道函数的返回类型。默认情况下,如果在该 typedef 中省略 void*,则假定 int 为返回类型 - 是的,这是正确的 C 代码。问题是编译器需要知道返回类型的大小才能正确操作堆栈。
您可以通过一些技巧来解决这个问题,例如,提前预先声明几种具有不同大小的返回类型的函数类型,然后选择您实际要调用的函数类型。但更简单的解决方案是要求插件中的函数始终返回 void* 或 int;通过作为参数给出的指针返回的实际结果。
您必须确保始终使用该函数应接受的确切数量和类型的参数来调用该函数。密切注意不同整数类型之间的差异(最好的选择是将参数显式转换为它们)。
多名评论者表示上面的代码不保证适用于可变参数函数(例如printf
).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)