Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to compile additional code at runtime in C or C++?

Tags:

Here is what I want to do:

  1. Run a program and initialize some data structures.
  2. Then compile additional code that can access/modify the existing data structures.
  3. Repeat step 2 as needed.

I want to be able to do this with both C and C++ using gcc (and eventually Java) on Unix-like systems (especially Linux and Mac OS X). The idea is to basically implement a read-eval-print loop for these languages that compiles expressions and statements as they are entered and uses them to modify existing data structures (something that is done all the time in scripting languages). I am writing this tool in python, which generates the C/C++ files, but this should not be relevant.

I have explored doing this with shared libraries but learned that modifying shared libraries does not affect programs that are already running. I have also tried using shared memory but could not find a way to load a function onto the heap. I have also considered using assembly code but have not yet attempted to do so.

I would prefer not to use any compilers other than gcc unless there is absolutely no way to do it in gcc.

If anyone has any ideas or knows how to do this, any help will be appreciated.

like image 437
Matt Avatar asked May 12 '12 14:05

Matt


Video Answer


2 Answers

There is one simple solution:

  1. create own library having special functions
  2. load created library
  3. execute functions from that library, pass structures as function variables

To use your structures you have to include same header files like in host application.

structs.h:

struct S {     int a,b; }; 

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; } 

output:

0 0 2 1 4 4 6 9 8 16 10 25 12 36 14 49 16 64 18 81 20 100 

You can also create mutable program that will be changing itself (source code), recompiling yourself and then replace it's actual execution with execv and save resources with shared memory.

like image 148
kravemir Avatar answered Oct 27 '22 13:10

kravemir


I think you may be able to accomplish this using dynamic libraries and loading them at runtime (using dlopen and friends).

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

You would obviously have to be compiling the new code as you go along, but if you keep replacing mynewcode.so I think this will work for you.

like image 26
Stephen Newell Avatar answered Oct 27 '22 15:10

Stephen Newell