1

我有以下用例,我以前用 Java 解决过,但现在需要将程序移植到 C。

我有一个方法 A,它调用了属于抽象类 Engine 的方法 do_work()。该类的每个具体实现构造如下:

用户将提交 do_work() 方法的定义。如果这个定义是正确的,程序员将使用 Java Compiler API 构造 Engine 类的具体实现。(此代码包含在下面以供参考)。

我怎样才能在 C 中做类似的事情:

我现在有一个结构体引擎,带有一个指向 do_work() 方法的函数指针。我希望用户能够在运行时通过命令行提交此方法(注意:这只发生一次,在启动时,一旦构造了引擎结构,我不想更改它)。

我该怎么办?我已经阅读了一些建议,说明我必须使用汇编来执行此操作,其他人则说这是不可能的,但没有一个给出很好的解释或参考。任何帮助,将不胜感激。

该解决方案不需要与 32/64 位机器兼容,因为所编写的程序仅适用于 64 位机器。

作为参考,Java 代码:

    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.
}
4

1 回答 1

2

在 C 中,所有代码在使用前都必须编译为本机代码,因此您唯一的方法是使用命令行编译器来构建用户提交的代码。例如,它可能是 GNU C++ 编译器,或 Visual C++ 编译器(但对于 Visual C++,我不知道法律问题是什么,许可证是否允许这样做)。所以,首先,选择你的编译器,可能是 GNU 的。

接下来,您可以将其编译为可执行程序或 DLL(假设您的软件适用于 Windows)。如果你决定将它编译成 DLL,你必须使用 Win32 函数 LoadLibrary 将新构建的 DLL 加载到你的进程中,然后你可以使用 GetProcAddress 函数获取方法地址并从 C++ 动态调用它(你必须实现一个函数包装器并在 DLL 中公开)。

如果您决定将其编译为 EXE 文件,则必须使用 CreateProcess 函数来运行您的代码,通过命令行发送参数并接收数据,可能是使用管道(请参阅 CreatePipe 函数),或者可能是临时文件,或任何Windows 中可用的其他进程间通信方式。

我认为在您的情况下,最好编译为 EXE 文件,因为在 DLL 中,如果用户代码有问题,您的主程序可能会崩溃。

于 2013-01-22T12:39:48.283 回答