你可以要求GCC从标准输入读取。阅读其文档中的
调用GCC章节。使用其
-x
选项与
/dev/stdin
或
-
:
echo 'int main(){return 0;}' | g++ -x c++ -O -Wall -o myprog /dev/stdin
顺便说一下,因为int main(){return 0;}
是一个有效的C程序,所以你可以使用它。
echo 'int main(){return 0;}' | gcc -x c -O -Wall -o myprog -
程序上,你应该考虑使用
popen(3) 来获取一个用于
pipe(7) 的
FILE*
句柄(所以
FILE* f = popen("g++ -x c++ -O -Wall -o myprog /dev/stdin", "w");
然后检查
f
不是空),并将内容写入其中,最后使用
pclose
关闭。别忘了测试
pclose
的状态。
然而,GCC 花费的大部分时间并非
解析(使用
-ftime-report
开发者选项 可以查看)。通常您需要要求它进行
优化(例如使用
-O2 -march=native
或仅使用
-O
),并且肯定需要要求所有
警告(至少使用
-Wall
,也可以使用
-Wextra
)。
如果你想要从发射的C++代码
/tmp/myemitted.cc
中生成一些
插件代码
/tmp/someplugin.so
,以便在Linux上
动态加载它,那么请将其编译为
位置无关代码,并将其编译为
共享对象动态库。例如:
g++ -o /tmp/someplugin.so -fPIC -shared -Wall -O /tmp/myemitted.cc
等等,然后在/tmp/someplugin.so
上使用dlopen(3),再用dlsym(3)获取一些已加载符号。我的GCC MELT正在执行此操作。
由于解析时间可以忽略不计,因此您可以在某个临时文件中编写C或C++代码(位于/tmp/
或/run
内,这在大多数Linux系统上通常是一些快速的tmpfs,因此写入它不需要磁盘I/O)。
最后,最近的GCC(至少使用GCC 6)还具有GCCJIT(实际上是libgccjit)。您可以使用它构建一些生成代码的表示,然后请求GCC进行编译。
请参阅this和that。阅读C++ dlopen mini howto和Program Library HowTo,以及Drepper的How To Write Shared Libraries。
我不想创建文件
生成临时文件(参见
mkstemp(3)等),你几乎也可以在
/tmp/
下生成一些以
.c
结尾的随机文件名,然后在其上注册一个函数使用
atexit(3)执行
unlink(2)...这样做非常快速(但在从中发出C++或C代码之前,应在内存中构建某种
AST)。使用一些
Makefile
通过一些
make
命令编译生成的代码具有优势(对于高级用户)可更改编译器或选项(通过编辑该
Makefile
来配置
make
)。
据我看来,你在避免使用临时文件方面是错误的(请注意,gcc
和g++
也会生成和删除临时文件,例如包含一些汇编代码的文件)。相反,我建议生成一个临时文件(匹配/tmp/mytemp*.cc
),并使用一些随机数(参见random(3);不要忘记在main
中早期使用例如srandom(time(NULL));
种子PRNG)。它可以非常简单。
char tmpbuf[80];
bool unique;
do { // in practice, this loop is extremely likely to run once
snprintf(tmpbuf, sizeof(tmpbuf), "/tmp/mytemp_%lx_p%d.cc",
random(), (int)getpid());
unique = access(tmpbuf, F_OK);
} while (unique);
// here tmpbuf contains a unique temporary file name
你编写了以下代码:
system("g++ -C "+code_string+" -o run.out");
注意,
+
通常不是字符串连接符。你可以使用
snprintf(3)或
asprintf(3)构建字符串。或者在C++中使用
std::string。如果你使用
system(3)函数,你应该检查它的返回代码:
char cmdbuf[128];
snprintf(cmdbuf, sizeof(cmdbuf), "g++ -Wall -O %s -o run.out", tmpbuf);
fflush(NULL);
if (system(cmdbuf) != 0) {
fprintf(stderr, "compilation %s failed\n", cmdbuf);
exit(EXIT_FAILURE);
}
顺便提一下,你的示例有误(缺少<stdio.h>
),这是C代码,而不是C++代码。应该是:
echo -e '#include <stdio.h>\nint main(){printf("Hello World"); return 0;}' \
| gcc -x c -Wall -O -o myprog -
PS. 我的回答是针对 Linux 的,但你可以根据你的操作系统进行调整。