有没有办法在运行时用C或C++编译其他代码?

Mat*_*att 15 c c++ linux gcc runtime-compilation

这是我想要做的:

  1. 运行程序并初始化一些数据结构.
  2. 然后编译可以访问/修改现有数据结构的其他代码.
  3. 根据需要重复步骤2.

我希望能够既要做到这一点C,并C++使用gcc(并最终Java在类Unix系统(特别是Linux和Mac OS X)).我们的想法是基本上为这些语言实现一个read-eval-print循环,它们在输入时编译表达式和语句,并使用它们来修改现有的数据结构(在脚本语言中一直都是这样).我正在编写这个工具python,它生成C/ C++文件,但这不应该是相关的.

我已经探讨了使用共享库执行此操作,但了解到修改共享库不会影响已在运行的程序.我也尝试过使用共享内存但无法找到将函数加载到堆上的方法.我还考虑过使用汇编代码但尚未尝试这样做.

我宁愿不使用任何编译器,gcc除非绝对没有办法gcc.

如果有人有任何想法或知道如何做到这一点,任何帮助将不胜感激.

kra*_*mir 13

有一个简单的解决方案:

  1. 创建具有特殊功能的自有库
  2. 加载创建的库
  3. 从该库执行函数,将结构作为函数变量传递

要使用您的结构,您必须包含相同的头文件,如在宿主应用程序中.

structs.h:

struct S {
    int a,b;
};
Run Code Online (Sandbox Code Playgroud)

main.cpp中:

#include <iostream>
#include <fstream>
#include <dlfcn.h>
#include <stdlib.h>

#include "structs.h"

using namespace std;

int main ( int argc, char **argv ) {

    // create own program
    ofstream f ( "tmp.cpp" );
    f << "#include<stdlib.h>\n#include \"structs.h\"\n extern \"C\" void F(S &s) { s.a += s.a; s.b *= s.b; }\n";
    f.close();

    // create library
    system ( "/usr/bin/gcc -shared tmp.cpp -o libtmp.so" );

    // load library        
    void * fLib = dlopen ( "./libtmp.so", RTLD_LAZY );
    if ( !fLib ) {
        cerr << "Cannot open library: " << dlerror() << '\n';
    }

    if ( fLib ) {
        int ( *fn ) ( S & ) = dlsym ( fLib, "F" );

        if ( fn ) {
            for(int i=0;i<11;i++) {
                S s;
                s.a = i;
                s.b = i;

                // use function
                fn(s);
                cout << s.a << " " << s.b << endl;
            }
        }
        dlclose ( fLib );
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0 0
2 1
4 4
6 9
8 16
10 25
12 36
14 49
16 64
18 81
20 100
Run Code Online (Sandbox Code Playgroud)

您还可以创建可更改的程序(源代码),重新编译自己,然后execv用共享内存替换它的实际执行并节省资源.


Ste*_*ell 12

我想你可以使用动态库并在运行时加载它们(使用dlopen和朋友)来实现这一点.

void * lib = dlopen("mynewcode.so", RTLD_LAZY);
if(lib) {
    void (*fn)(void) = dlsym(lib, "libfunc");

    if(fn) fn();
    dlclose(lib);
}
Run Code Online (Sandbox Code Playgroud)

您显然必须在进行时编译新代码,但如果您继续更换,mynewcode.so我认为这对您有用.

  • 应该支持加载,但我不确定在所有情况下都支持*un*加载. (2认同)

Mat*_* M. 5

尽管 LLVM 现在主要用于其在编译中的优化和后端角色,但它的核心是低级虚拟机。

LLVM 可以 JIT 代码,即使返回类型可能非常不透明,因此如果您准备围绕它包装自己的代码并且不要太担心将要发生的强制转换,它可能会对您有所帮助。

然而,C 和 C++ 对这种事情并不是很友好。