1

I have the following use case which I had previously solved in Java, but am now required to port the program to C.

I had a method A which called a method do_work() belonging to an abstract class Engine. Each concrete implementation of the class was constructed as follows:

users would submit the definition of the do_work() method . If this definition was correct, the programmer would construct a concrete implementation of the Engine class using the Java Compiler API. (code for this is included for reference below).

How can I do something similar in C:

I now have a structure Engine, with a function pointer to the do_work() method. I want users to be able to submit this method at run time (note: this only occurs once, on startup, once the Engine structure has been constructed, I do not want to change it) via command line.

How could I go about this? I've read around suggestions stating that I would have to use assembly to do this, others stating that this was not possible, but none of them giving a good explanation or references. Any help would be appreciated.

The solution doesn't need to be compatible with 32/64 bits machines, as the program this is written for is only for 64 bits machines.

For reference, the Java Code:

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

    StandardJavaFileManager stdFileManager = compiler
            .getStandardFileManager(null, Locale.getDefault(), null);
    Iterable<? extends JavaFileObject> compilationUnits = null;

    String[] compileOptions = new String[] { "-d", "bin" };
    Iterable<String> compilationOptions = Arrays.asList(compileOptions);


        SimpleJavaFileObject fileObject = new DynamicJavaSourceCodeObject(
                "package.adress",getCode());
        JavaFileObject javaFileObjects[] = new JavaFileObject[] { fileObject };
        compilationUnits = Arrays.asList(javaFileObjects);
    }

    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
    CompilationTask compilerTask = compiler.getTask(null, stdFileManager,
            diagnostics, compilationOptions, null, compilationUnits);

    boolean status = compilerTask.call();

    if (!status) {// If compilation error occurs
        /* Iterate through each compilation problem and print it */
        String result = ""; 
        for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
            result = String.format("Error on line %d in %s",
                    diagnostic.getLineNumber(), diagnostic);
        }
        Exception e = new Exception(result);
        throw e;
    }

    stdFileManager.close();// Close the file manager

    /*
     * Assuming that the Policy has been successfully compiled, create a new
     * instance
     */

    Class newEngine = Class
            .forName("package.name");

    Constructor[] constructor = newPolicy.getConstructors();
    constructor[0].setAccessible(true);
    etc.
}
user1018513
  • 1,682
  • 1
  • 20
  • 42
  • The following may be an answer to your question (not sure if it is an exact duplicate but I think it could bring you some keyword) http://stackoverflow.com/questions/1441947/dynamic-code-compilation – greydet Jan 22 '13 at 11:44

1 Answers1

2

In C all code must be compiled to native one before usage, so the only way for you is to use command line compiler to build code submitted by users. It may be GNU C++ compiler for example, or Visual C++ compiler (but for Visual C++ I don't know what about legal problems, is it permitted by license to do that). So, first of all, select your compiler, probably GNU one.

Next, you can compile it as executable program or as DLL (assuming your software is for Windows). If you decide to compile it to DLL, you have to use Win32 function LoadLibrary to load new built DLL into your process, and after that you can use GetProcAddress function to get method address and call it dynamically from C++ (you must implement a function wrapper and make it public in DLL).

If you decide to compile it as EXE file, you have to use CreateProcess function to run your code, send parameters via command line and receive data, may be, with pipe (see CreatePipe function), or may be with temporary file, or any other interprocess communication way available in Windows.

I think in your situation it is better to compile to EXE file, because in DLL if user code is buggy your main program may crash.

Vitalii
  • 4,434
  • 4
  • 35
  • 77
  • The software is not for Windows. – user1018513 Jan 22 '13 at 14:11
  • But ideas are the same for Linux too (and Mac OS is also actually Linux). You can do exactly the same: use GCC to compile custom code to executable file and run it with system function for example, write output to temporary file and read it in your program. – Vitalii Jan 22 '13 at 15:31
  • this is not the use case though. This is not running a program, separate process or even a thread. this is emulating the Java Compiler API to enable the definition of a method to be specified later. There is no requirement for it to be in the same binary, but does have to be in the same program with no context switch. The compiled definition of do_method should be no different than if it had been specified at compiled time. – user1018513 Jan 22 '13 at 15:58
  • Well, C is not Java, you can not receive exactly the same result. The most similar way is to compile it to shared library with GCC command line interface and load it with http://linux.die.net/man/3/dlopen system call. If you can not run separate process (even GCC to compile code), the only way for you is to implement your own C compiler I think. As I know, for now there are no any C compiler implemented as static or dynamic library that you can embed into your code; of course, you can try to convert GCC from command line tool to static library, but I think it will not be easy job. – Vitalii Jan 23 '13 at 10:42