I read about eval in C, and it makes sense that if you write a C string parser/evaluator, you can just map it to specific functions in your main C program. But it doesn't actually place it into executable memory from what I understand, like a JIT compiler seems to do. I don't fully understand JIT compilers (I never made one) but I get the gist.
So what I'm wondering is if you can create sort of a JIT compiler in C without doing too much work of parsing C strings and converting to ASTs and whatnot. Basically, can you do like in JavaScript and dynamically create a function (in C), such that that function is exactly the same as any other C function (i.e. it is compiled directly into executable machine code in the executable part of the program sort of thing).
If it's not possible to do that, a second approach would be to dynamically load C imports/files/modules. So you spin off a process that tells the clang compiler to compile some library function(s), and after it's done, without stopping the current program, it links/attaches that new program library to itself, and so can execute the code that way.
If that's not possible, maybe an option is to simply recompile the program in the background, then swap the current program with the new program which boots up from scratch. That would just be very primitive though.
Trying to figure out if you have some structs for your own custom function datatype in C, how you can then execute that function in C in the most optimized way.
On POSIX systems (Linix, Mac, UNIX) you have the dlopen
and dlsym
functions you can work with. These functions can be used to load a shared library at run time and execute a function from it.
As far as creating a library, the simplest thing to do would be to write the relevant source code to a file, run gcc in a separate process to compile it, then use dlopen
/dlsym
to run the functions it contains.
For example:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
const char *libsrc =
"#include <stdio.h>\n"
"\n"
"void f1()\n"
"{\n"
" printf(\"in f1\\n\");\n"
"}\n"
"\n"
"int add(int a, int b)\n"
"{\n"
" return a+b;\n"
"}\n";
int main()
{
FILE *libfile = fopen("mylib.c", "w");
fputs(libsrc, libfile);
fclose(libfile);
system("gcc -fPIC -shared -g -Wall -Wextra -o libmylib.so mylib.c");
void *lib = dlopen("libmylib.so", RTLD_NOW);
if (!lib) {
printf("dlopen failed: %s\n", dlerror());
return 1;
}
void (*f)() = dlsym(lib, "f1");
if (f) {
f();
} else {
printf("dlsym for f1 failed: %s\n", dlerror());
}
int (*a)(int, int) = dlsym(lib, "add");
if (a) {
int x = a(2,3);
printf("x=%d\n", x);
} else {
printf("dlsym for add failed: %s\n", dlerror());
}
dlclose(lib);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With