Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
您能动态编译C代码并将其链接/加载到C程序中吗?_C_Jit - Fatal编程技术网

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

您能动态编译C代码并将其链接/加载到C程序中吗?,c,jit,C,Jit,我读过,如果你写一个C字符串解析器/计算器,你可以把它映射到主C程序中的特定函数。但据我所知,它实际上并没有像a一样将其放入可执行内存中。我不完全理解JIT编译器(我从来没有做过),但我明白了要点 所以我想知道的是,您是否可以在C中创建某种JIT编译器,而不必做太多解析C字符串和转换为AST之类的工作。基本上,您可以像JavaScript一样动态创建一个函数(在C中),这样该函数就可以与任何其他C函数完全相同(即,在程序的可执行部分直接编译成可执行机器代码之类的东西) 如果不可能做到这一点,第二

我读过,如果你写一个C字符串解析器/计算器,你可以把它映射到主C程序中的特定函数。但据我所知,它实际上并没有像a一样将其放入可执行内存中。我不完全理解JIT编译器(我从来没有做过),但我明白了要点

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

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

如果这是不可能的,也许可以选择在后台重新编译程序,然后将当前程序与从头启动的新程序交换。但那将是非常原始的

试图弄清楚,如果您在C中有一些自定义函数数据类型的结构,那么您可以如何以最优化的方式在C中执行该函数。

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

就创建库而言,最简单的方法是将相关的源代码写入文件,在单独的过程中运行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;
}
#包括
#包括
#包括
常量字符*libsrc=
“#包括\n”
“\n”
“无效f1()\n”
“{\n”
printf(\“在f1\\n\”);\n
“}\n”
“\n”
整数添加(整数a,整数b)\n
“{\n”
“返回a+b;\n”
“}\n”;
int main()
{
FILE*libfile=fopen(“mylib.c”、“w”);
FPUT(libsrc、libfile);
fclose(libfile);
系统(“gcc-fPIC-shared-g-Wall-Wextra-o libmylib.so mylib.c”);
void*lib=dlopen(“libmylib.so”,RTLD_NOW);
if(!lib){
printf(“dlopen失败:%s\n”,dlerror());
返回1;
}
void(*f)(=dlsym(lib,“f1”);
如果(f){
f();
}否则{
printf(“f1的dlsym失败:%s\n”,dlerror());
}
int(*a)(int,int)=dlsym(lib,“add”);
如果(a){
int x=a(2,3);
printf(“x=%d\n”,x);
}否则{
printf(“添加的dlsym失败:%s\n”,dlerror());
}
dlclose(lib);
返回0;
}

还有一个微型C编译器,可以用作库,使用它,您可以动态编译程序,并从现有代码中调用新编译代码中的函数,而无需借助动态库加载

代码不会是最优化的C语言,但也不会太糟糕



虽然这通常不是像C一样的HLL,但只是简单的数学表达式。如果您的需求相当简单,那么这可能是一条路线。通常,它用于简单的函数,这些函数由于在2D/3D绘图或图像转换中使用而对速度敏感

您链接到的问题中显示了编译C代码并将结果链接到当前程序的方法。这正是你在第三段中所要求的。当然,在典型的通用系统中,完全在主存而不是磁盘或其他存储器中编译代码并执行该代码是可能的,但这当然比调用现有的编译器和链接器要多得多,并且需要对目标系统上的ABI有详细的了解……实际上,调用编译器和链接器基本上是不值得的,除非是作为一项学术练习,而在内存中完成这一切就更不值得了。当然,“如果您在C中有一些自定义函数数据类型的结构”,那么以这种方式执行函数将不是“最优化的方式”。dlopen(Unix)或LoadLibrary(Windows)是否适合您的需要?他们将编译后的二进制文件加载到可执行内存中。我曾经编写过一个完整的C解释器来完成所有这些。这是一个有趣的挑战——困难,但可行。今天,这变得更加困难,也更加容易,因为事情变得更加复杂,尽管现在有一些库可以完成我必须手工完成的一些事情。(续)(1)如果你想加载并动态链接到
文件中的代码,那么
dlopen
就是为了这个目的。(2) 如果您想跳转到已加载的任意代码(传递任意参数),这就是它的用途。(3) 如果您想加载并动态链接到单个
.o
文件(或老式的静态
.a
库),我不知道有什么好方法可以做到这一点,我很想把旧的自制动态链接器掸掉,教它现代对象文件格式。