你能动态编译和 link/load C 代码成 C 程序吗?

Can you dynamically compile and link/load C code into a C program?

我看了一下eval in C, and it makes sense that if you write a C string parser/evaluator, you can just map it to specific functions in your main C program. But it doesn't actually place it into executable memory from what I understand, like a JIT compiler好像是这样的。我不完全理解 JIT 编译器(我从来没有做过)但我明白了要点。

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

如果无法做到这一点,第二种方法是动态加载 C imports/files/modules。所以你分拆了一个进程,告诉 clang 编译器编译一些库函数,完成后,在不停止当前程序的情况下,它 links/attaches 新程序库到它自己,因此可以执行代码那样.

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

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

在 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;
}

还有可以用作库的 Tiny C 编译器,您可以使用它即时编译程序并从现有代码调用新编译代码中的函数 求助于动态库加载。

代码可能不是最优化的 C,但也不算太差。

An example in this answer.

除了 dlload 路径之外,一些表达式计算器和 SIMD 数学内核工具将动态代码生成到内存块中,该内存块可通过 mprotect(2) 和 PROT_EXEC.

尽管这通常不是像 C 那样的 HLL,而只是简单的数学表达式。如果您的要求相当简单,那可能是一条路线。通常它用于简单的功能,这些功能由于它们的使用而对速度敏感,例如。 2D/3D 绘图或图像转换