您可以动态编译C代码并将其链接/加载到C程序中吗?

时间:2019-07-01 01:57:09

标签: c jit

我读到了eval in C的内容,这很有意义,如果您编写一个C字符串解析器/评估器,则可以将其映射到主C程序中的特定函数。但是它实际上并没有按照我的理解将其放入可执行内存中,就像JIT compiler似乎可以做到的那样。我对JIT编译器不完全了解(我从来没有做过),但我了解到要点。

所以我想知道的是,您是否可以在C中创建某种JIT编译器,而无需进行过多的解析C字符串并将其转换为AST的工作。基本上,您可以像在JavaScript中那样做并动态创建一个函数(在C中),以便该函数与任何其他C函数完全相同(即,将其直接编译编译为可执行文件中的可执行代码)。程序的可执行部分)。

如果不可能这样做,第二种方法是动态加载C导入/文件/模块。因此,您将启动一个告诉clang编译器编译某些库函数的过程,然后在完成后不停止当前程序的情况下,它将新程序库链接/附加到其自身,从而可以执行代码那样

如果不可能,则可能的选择是简单地在后台重新编译程序,然后将当前程序与从头启动的新程序交换。不过那将是非常原始的。

试图弄清楚在C中您自己的自定义函数数据类型是否具有某些结构,然后如何以最优化的方式在C中执行该函数。

3 个答案:

答案 0 :(得分:4)

在POSIX系统(Linix,Mac,UNIX)上,您可以使用dlopendlsym函数。这些函数可用于在运行时加载共享库并从中执行一个函数。

就创建一个库而言,最简单的方法是将相关的源代码写入文件,在单独的进程中运行gcc进行编译,然后使用dlopen / dlsym运行其中包含的功能。

例如:

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

const char *libsrc =
"#include <stdio.h>\n"
"\n"
"void f1()\n"
"{\n"
"  printf(\"in f1\\n\");\n"
"}\n"
"\n"
"int add(int a, int b)\n"
"{\n"
"  return a+b;\n"
"}\n";

int main()
{
    FILE *libfile = fopen("mylib.c", "w");
    fputs(libsrc, libfile);
    fclose(libfile);
    system("gcc -fPIC -shared -g -Wall -Wextra -o libmylib.so mylib.c");

    void *lib = dlopen("libmylib.so", RTLD_NOW);
    if (!lib) {
        printf("dlopen failed: %s\n", dlerror());
        return 1;
    }

    void (*f)() = dlsym(lib, "f1");
    if (f) {
        f();
    } else {
        printf("dlsym for f1 failed: %s\n", dlerror());
    }

    int (*a)(int, int) = dlsym(lib, "add");
    if (a) {
        int x = a(2,3);
        printf("x=%d\n", x);
    } else {
        printf("dlsym for add failed: %s\n", dlerror());
    }

    dlclose(lib);
    return 0;
}

答案 1 :(得分:2)

还有一个Tiny C编译器可用作库,您可以使用它快速编译程序并从现有代码调用新编译的代码中的函数,而不必求助于< / em>动态库加载。

该代码可能不是最优化的C语言,但也不错。

An example in this answer

答案 2 :(得分:0)

除了dlload路由外,一些表达式评估器和SIMD数学内核工具还可以动态地将代码生成到内存块中,该内存块可以通过 mprotect(2)和PROT_EXEC进行执行。

尽管通常不是像C那样的HLL,而是简单的数学表达式。如果您的要求很简单,那可能是一条路线。通常,由于其在例如图形用户界面中的用法,它用于对速度敏感的简单功能。 2D / 3D绘图或图像转换