如何在执行期间编译C代码,并获得指向相应函数的指针?

时间:2014-10-15 21:32:37

标签: c compilation jit

假设我在执行期间生成了一个C程序:

source = "int add_x_y(int x, int y){ return x + y; }";
source_size = 42;

我想要以下功能:

void* compile(char* source, int source_size);

这样:

int (*f)(int,int) = compile(source, source_size);
printf("%d\n",f(2,3));

输出:

5

并且compile不能依赖外部工具(编译器),因为我想在emscripten(将C程序转换为.js文件)中使用它。

这可能吗?

2 个答案:

答案 0 :(得分:1)

其他人可能比我更好地填写一些细节,但如果你不介意呼唤GCC或链接到它,它应该是可行的。如果将代码写入文件,则将文件编译为共享库(.SO)。从那里开始,只需加载共享库并获取所需符号的地址即可。

答案 1 :(得分:0)

它是特定于操作系统和处理器的。我想你是Linux x86-64(64位x86)或ia32(32位x86)

您可以使用tinycc(它是一个可以快速编译C代码到非常慢和未经优化的机器代码的编译器),它提供了一个包含libtcc函数的库tcc_compile_string

您可以使用JIT-compilinglibjitGNU lightningasmjitLLVM库(GCC 5将有JIT-ing abilities)。

你只需将你的字符串写入一些临时C文件/tmp/genfoo.c(如果该文件位于tmpfs文件系统中,则不涉及真正的磁盘IO,因此速度很快)然后分叉真正的命令:

gcc -Wall -fPIC -shared -O /tmp/genfoo.c -o /tmp/genfoo.so

然后dlopen(3)生成的/tmp/genfoo.so共享对象(和dlsym从其名称中获取函数指针)。

如果您想要生成生成的代码,则需要真实的optimizing compiler GCCClang/LLVM;编写临时源文件(并在编译器中解析)的开销可以忽略不计:大部分工作都在优化过程中的编译器内部。 Generating C code是实用的,特别是当您希望某些C编译器对生成的代码进行优化时。

请注意,所有这些技术可能都不会在emscripten内工作,原因很简单,因为您可能无法将数据指针强制转换为函数指针(从法律上讲,强制转换可能是C99中未指定的行为,但所有我上面提到的方法需要它,你在你的问题中做这样的演员)!如果您需要在浏览器中生成代码 ,则可能需要生成一些Javascript或其子集(例如asm.js)。见calling Javascript from C/C++ in Emscripten

如果您正在开发要在浏览器中运行的语言,请使该语言生成一些Javascript(例如asm.js)。

另请参阅NaCl(Google浏览器上的Native Client)