¿Cómo comstackr un código C durante el tiempo de ejecución y obtener un puntero a la función correspondiente?

Supongamos que genero un progtwig en C durante el tiempo de ejecución:

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

Quiero la siguiente función:

 void* compile(char* source, int source_size); 

Tal que

 int (*f)(int,int) = compile(source, source_size); printf("%d\n",f(2,3)); 

Salidas:

 5 

Y compile no puede depender de herramientas externas (comstackdores), ya que me gustaría usarlo en emscripten (que convierte un progtwig en C a un archivo .js).

¿Es eso posible?

Probablemente alguien más pueda completar algunos de los detalles mejor que yo, pero si no te importa llamar a GCC o vincularlo, debería ser factible. Si escribe el código en un archivo, compile el archivo en una biblioteca compartida (.SO). A partir de ahí, es una simple cuestión de cargar la biblioteca compartida y obtener la dirección del símbolo deseado.

Es sistema operativo y procesador específico. Supongo que estás en Linux x86-64 (64 bits x86) o ia32 (32 bits x86)

Podría usar tinycc (es un comstackdor que comstack rápidamente el código C a un código de máquina muy lento y no optimizado) que proporciona una biblioteca libtcc contiene una función tcc_compile_string .

Podría usar una biblioteca de comstackción JIT como libjit , GNU lightning , asmjit , LLVM (y GCC 5 tendrá capacidades de JIT-ing ).

Y simplemente puede escribir su cadena en algún archivo C temporal /tmp/genfoo.c (si ese archivo se encuentra en un sistema de archivos tmpfs , no se trata de un IO de disco real, por lo que es rápido) y luego ejecute un comando real:

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

luego dlopen (3) el objeto compartido /tmp/genfoo.so producido (y dlsym para obtener un puntero a función de su nombre).

Si desea obtener el rendimiento del código generado, necesita un comstackdor de optimización real como GCC o Clang / LLVM ; la sobrecarga de escribir un archivo fuente temporal (y analizarlo en el comstackdor) es insignificante: la mayor parte del trabajo está dentro del comstackdor en las pasadas de optimización. La generación de código C es práctica, especialmente cuando desea que el comstackdor C optimice el código generado.

Tenga en cuenta que todas estas técnicas probablemente no funcionarán dentro de emscripten , simplemente porque probablemente no pueda lanzar un puntero de datos a un puntero de función allí (legalmente, ese lanzamiento es probablemente un comportamiento no especificado en C99, pero todos los enfoques que mencioné anteriormente lo necesitan, y usted están haciendo tal reparto en tu pregunta)! Si necesita generar código dentro de un navegador, probablemente necesite generar algo de Javascript o un subconjunto de él (por ejemplo, para asm.js ). Ver llamando a Javascript desde C / C ++ en Emscripten

Si está desarrollando un lenguaje para ejecutarse dentro del navegador, haga que ese lenguaje genere un poco de Javascript (por ejemplo, asm.js ).

Véase también NaCl (Cliente nativo en los navegadores Google)