Josh Weinstein
Josh Weinstein

Reputation: 2968

Compile and Run a string of C source code

So, I want to compile and run a string of C source code, where the string is a const char* and represents an entire program. It should be taken from either a constant or constructed string, such as

const char* prog = "#include <stdio.h> int main(void) {puts(\"foo\"); return 0;}"

I have already tried tcclib, but it currently doesn't build on Mac OS and due to lack of a consistent maintainer I don't think it's a viable way to do this.

I am mainly asking about this as a means to have a backend for a programming language that compiles to C. If there is some library function in gcc or clang, that would work too.

Note: This is specifically about compiling C code from C, not injecting it into a process.

Upvotes: 1

Views: 1895

Answers (1)

Nick ODell
Nick ODell

Reputation: 25249

@bruno My idea was not having to deal with different windows and unix path names (windows utf-16 pathnames). But perhaps just calling gcc is a preferable solution.

I think calling GCC is easiest. However, just because you're calling GCC as an external process, doesn't mean you have to write your generated C to a file.

GCC is capable of taking its output from standard in. Here's an example, written in Bash.

echo "main(){}" | gcc -x c -

Here's the same thing in C:

#include <stdio.h>
#include <string.h>

const char *prog = "#include <stdio.h>\nint main(void) {puts(\"foo\"); return 0;}";

int main() {
    FILE *proc = popen("gcc -x c -", "w");
    fwrite(prog, sizeof(char), strlen(prog), proc);
    pclose(proc);
}

And here's the same thing, but with error handling:

#include <stdio.h>
#include <string.h>

const char *prog = "#include <stdio.h>\nint main(void) {puts(\"foo\"); return 0;}";

int main() {
    FILE *proc = popen("gcc -x c -", "w");
    if(!proc) {
        perror("popen gcc");
    }
    fwrite(prog, sizeof(char), strlen(prog), proc);
    if(ferror(proc)) {
        perror("writing prog");
    }
    if(pclose(proc) == -1) {
        perror("pclose gcc");
    }
}

I think that's the best way of accomplishing this.

Upvotes: 4

Related Questions