来自 this site ,我了解到一个非常令人兴奋的事实,即您可以从共享库加载和运行代码,而无需使用它显式编译您的程序。
以下代码片段说明了如何使用 dlopen()
(和相关函数)运行 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 语言),我想让用户能够选择一个共享库并从中运行代码。我知道这是可能的,因为许多语言(包括 Python 和 J,都是用 C 编写的)可以使用 dlopen()
动态调用函数,只知道在运行时将传递给函数和从函数返回什么.
但是,我无法提前预测我需要如何转换从 dlsym()
返回的 void 指针。在上面的代码中,程序员知道他们要查找的符号(“cos”)是一个使用一个 double 作为参数并返回一个 double 的函数,所以他们知道他们必须如何转换 余弦
变量为“指向接受 double 并返回 double 的函数的指针”。
如果我想编写一个用户指定文件名和函数原型(prototype)的程序,我该如何编写调用 dlsym() 并正确调用该函数的底层 C 代码?
我的理论是您需要直接从进程的堆栈中压入参数并弹出返回值(如果没有内联汇编我不知道该怎么做,我想避免这种情况),但是这由于您可能需要通过寄存器传递参数而变得复杂。有人知道如何处理吗?
最佳答案
有一个众所周知的库可以解决这个问题,被许多解释语言使用:libffi .
当然,这个库在内部使用汇编代码,但它有很多硬件和软件后端,您可以将其视为可移植解决方案。
关于c - 在编译时不知道原型(prototype)的情况下使用函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47249532/