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

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

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

我想要以下function:

 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文件)中使用它。

那可能吗?

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

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

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

您可以使用JIT编译库,如libjit , GNU lightning , asmjit , LLVM (以及GCC 5将具有JIT-ingfunction )。

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

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

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

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

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

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

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