c - 在编译时不知道原型(prototype)的情况下使用函数指针

标签 c linux dlopen

来自 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/

相关文章:

c++ - 如何dlopen jemalloc动态库

c - 二维数组的定义和索引 - C

python - 将 OpenGL 模型导出为 .OBJ

c - 调用数组的特定索引时,打印所有值

php - cron 时间限制的解决方法

c - dlopen() 搜索路径

c - 简单的 pic10f204 C 编程

linux - 重命名目录中的多个文件

windows - C/C++中的跨平台unicode : Which encoding to use?

linux - "same library"的 dlopen 定义