我希望能够动态生成C代码,并快速重新加载到正在运行的C程序中。
我在Linux上,怎么做呢?
在Linux上,可以重新编译和重新加载库文件.so吗?
是否可以在不生成.so文件的情况下进行编译,将编译后的输出存储在内存中,然后重新加载?我希望能够快速重新加载已编译的代码。
我希望能够动态生成C代码,并快速重新加载到正在运行的C程序中。
我在Linux上,怎么做呢?
在Linux上,可以重新编译和重新加载库文件.so吗?
是否可以在不生成.so文件的情况下进行编译,将编译后的输出存储在内存中,然后重新加载?我希望能够快速重新加载已编译的代码。
其次,生成C代码的主要原因是为了利用优秀的优化编译器(另一个原因是C的可移植性和普及性)。如果您不关心生成代码的性能(TCC将C编译成非常天真且缓慢的机器码),则可以使用其他方法,例如使用一些JIT库,如Gnu lightning(生成缓慢的机器码非常快速),Gnu Libjit或ASMJIT(生成的机器码稍微好一些),LLVM或GCCJIT(生成良好的机器码,但生成时间与编译器相当)。
如果您生成C代码并希望其运行速度快,那么C代码的编译时间是不可忽略的(因为您可能会分叉一个gcc -O -fPIC -shared
命令来制作一些共享对象foo.so
,以此来从您生成的foo.c
中)。根据经验,生成C代码所需的时间比编译它所需的时间少得多(使用gcc -O
)。在MELT中,生成C代码的速度比通过GCC编译它要快10倍以上(通常是30倍以上)。但是,由C编译器进行的优化是值得的。您问道:
当然,是的:你应该派生一个命令来从生成的C代码构建库(例如在Linux上,库文件
.so
能否在运行时重新编译和重新加载?
gcc -O -fPIC -shared generated.c -o generated.so
),但你也可以间接地这样做,例如通过运行 make -j
,特别是如果 generated.so
太大而使得将 generated.c
分为多个C生成文件变得相关!然后,您使用 dlopen 动态加载您的库(给出完整路径,如 /some/file/path/to/generated.so
,可能还要使用 RTLD_NOW
标志)并且必须使用 dlsym
查找相关符号。不要考虑重新加载(第二次)相同的 generated.so
,最好发出唯一的 generated1.c
(然后是 generated2.c
等) C文件,然后将其编译为唯一的 generated1.so
(第二次生成为 generated2.so
等),然后 dlopen
它(这可以做很多十万次)。您可能希望在发出的 generated*.c
文件中有一些 constructor 函数,在 generated*.so
的 dlopen
时间执行它们。
您的基础应用程序应该定义了一种关于dlsym-ed名称(通常是函数)以及如何调用它们的约定。它只能直接通过dlsym
的函数指针调用generated*.so
中的函数。在实践中,您可以决定每个generated*.c
文件定义一个void dynfoo(int)
和int dynbar(int,int)
函数,并使用"dynfoo"
和"dynbar"
进行dlsym
,并通过函数指针(由dlsym
返回)调用它们。您还应该定义如何以及何时调用这些dynfoo
和dynbar
的约定。最好使用-rdynamic
将基础应用程序链接起来,以便您的generated*.c
文件可以调用您的应用程序函数。
您不希望generated*.so
重新定义现有名称。例如,您不希望在您的generated*.c
中重新定义malloc
并期望所有堆分配函数自动使用您的新变量(这可能不起作用,��使起作用也很危险)。
您可能不会费心去dlclose
一个动态加载的共享对象,除非在应用程序清理和退出时(但我根本不费心去dlclose
)。如果您确实dlclose
了一些动态加载的generated*.so
文件,请确保没有任何指针,甚至是调用框架中的返回地址存在于其中。
P.S. MELT翻译器目前是57KLOC的MELT代码转换为将近1770KLOC的C代码。
gcc -O
生成的代码慢2到3倍)。 - Basile Starynkevitch你确定C语言在这里是正确的答案吗?有许多解释性语言,比如Lua、Bigloo Scheme,甚至可能是Python,它们非常适合嵌入到现有的C应用程序中。您可以使用扩展语言编写动态部分,该语言将支持在运行时重新加载代码。
明显的缺点是性能 - 如果您绝对需要编译后的C语言原始速度,则这些可能不可行。
dlopen
函数(参见 mans)。它打开一个库.so文件并返回一个void*指针,然后你可以使用dlsym
获取库中任何函数/变量的指针。dlopen
和 dlsym
(不是 dl_open
……)! - Basile Starynkevitch