从this site开始,我学到了一个令人兴奋的事实,即您可以从共享库加载和运行代码,而无需使用它明确地编译您的程序。
以下代码片段说明了如何使用dlopen()
(及相关函数)从C&C的数学库(libm)运行double cos(double)
函数:
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
printf ("%f\n", (*cosine)(2.0));
dlclose(handle);
}
作为一种爱好,我一直在为自定义语言编写一个解释器(在C中),并且我希望用户能够选择共享库并从中运行代码。我知道这是可能的,因为许多语言(包括用C语言编写的Python和J)都可以使用dlopen()
动态调用函数,只能在运行时知道将传递给函数并从函数返回的内容。
但是,我无法提前预测我将如何转换从dlsym()
返回的void指针。在上面的代码中,程序员知道他们要查找的符号(&#34; cos&#34;)是一个函数,使用一个double作为参数并返回一个double,因此他们知道如何投射cosine
变量为&#34;指向函数的指针,该函数接受double并返回double&#34;。
如果我想编写一个用户指定文件名和函数原型的程序,我怎样才能编写调用dlsym()并正确调用函数的底层C代码?
我的理论是,您需要直接从流程堆栈中推送参数和弹出返回值(我不知道如何在没有内联汇编的情况下执行此操作,而我是这样做的。我希望避免),但由于您可能需要通过寄存器传递参数,这会变得复杂。有人知道如何处理这个吗?