将Java嵌入到C++应用程序中?

26

我得到了一个用C++编写的应用程序,并且我能够通过为其编写C++插件来扩展应用程序的功能。

基本上我想要做的是将Java嵌入到这个应用程序中。这已经用Python完成了(不是我完成的)。

我读到了关于JNI的一些东西,但总是有一个使用Java类的完整程序的讲话。

我想做的是使用C++中的类在Java中与应用程序交互。
在这种情况下,它是一个名为Cinema 4D的3D应用程序。

是否有办法在应用程序运行时编译和评估Java代码(使用JNI或类似工具的某种脚本语言)?

嵌入完成后的虚构代码示例:

import c4d.documents.*;

class Main {
  public static void main() {
    BaseDocument doc = GetActiveDocument();
    BaseObject op = doc.GetActiveObject();
    if (op != null) {
      op.Remove();
    }
  }
}

这段代码应该与Cinema 4D交互,以删除所选对象。


你需要完整的Java SE还是只需要一些最小的虚拟机? - Michał Šrajer
如果你已经确定这种语言必须是Java,为什么还要说“某种脚本语言”? - jalf
@MichałŠrajer 这个问题实际上仍然没有解决,Java和应用程序之间的基本交互对于入门非常有帮助。 - Niklas R
@jalf:不应该需要重新启动应用程序才能运行新添加的Java代码,我想在C4D中编写一个“IDE”,可以直接运行代码。 - Niklas R
@NiklasR - “基本交互”听起来像是使用套接字的一个很好的任务。 - Flexo
@awoodland 我需要解释来自客户端的字节。如果我不编写一个全新的解释器,那么可能性就不会太多了。^^ - Niklas R
6个回答

53

你可以在应用程序中嵌入JVM。Oracle的官方参考书有更多细节。总结如下:

#include <jni.h>       /* where everything is defined */

int main() {
  JavaVM *jvm;       /* denotes a Java VM */
  JNIEnv *env;       /* pointer to native method interface */
  JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */
  vm_args.version = 0x00010001; /* New in 1.1.2: VM version */
  /* Get the default initialization arguments and set the class 
   * path */
  JNI_GetDefaultJavaVMInitArgs(&vm_args);
  vm_args.classpath = ...;
  /* load and initialize a Java VM, return a JNI interface 
   * pointer in env */
  JNI_CreateJavaVM(&jvm, &env, &vm_args);
  /* invoke the Main.test method using the JNI */
  jclass cls = env->FindClass("Main");
  jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V");
  env->CallStaticVoidMethod(cls, mid, 100);
  /* We could have created an Object and called methods on it instead */
  /* We are done. */
  jvm->DestroyJavaVM();
}
你可以做更复杂的事情(例如自定义类加载器),但这就是在应用程序中使JVM运行所需的最低要求。

现在,这是用C ++调用Java方法吗?实际上我需要相反的方式 :) - Niklas R
4
使用Swig,您可以生成绑定代码,从而允许您从Java中调用C++代码。 问题暗示您希望以这种方式实现。 您还可以在一个程序中同时实现两者。 - Flexo
我的建议是:既然楼主想要加载插件,我认为他也应该了解如何使用自定义类加载器来读取“插件jar”文件。此外,您需要使用带有本地方法(即JNI)的Java类来从Java中调用C ++。 - Eduardo Costa

4
有些混淆,不确定您是想将Java嵌入到C++应用程序中还是反之。我会分别讨论这两种情况。
1. 对于将Java嵌入到C++应用程序中,您可以通过套接字调用Java程序。在Java端,您使用SocketServer,在C++端,您使用通用套接字层库。这是迄今为止最简单、最可扩展的方法。随着Java工作量的增加,您可以不断添加额外的JVM。部署略微复杂,但非常有效。
2. 对于将C++应用程序嵌入到Java中,这很简单。您将C++应用程序编译成共享库,并使用JNI来调用它。

2
我想做的基本上是将Java嵌入到这个应用程序中。Python已经完成了这个工作(不是我完成的)。
JNI调用API支持此操作,如@awoodland所述。这是Java 6/7的当前链接
我想要做的是,在Java中使用C++类与应用程序进行交互。在这种情况下,它是一个名为Cinema 4D的3D应用程序。
为此,您可以使用以下之一:
- 在C中实现的Java原生方法 - JNA - SWIG 是否有一种方法可以在应用程序运行时编译和评估Java代码(使用JNI或类似的东西中的某种脚本语言)?
"

BeanShellGroovy等,可能会引起您的兴趣。两者都支持在JVM上运行的动态解释代码。

"

要从Java调用C ++,我建议您也查看[BridJ](http://code.google.com/p/bridj)+ [JNAerator](http://code.google.com/p/jnaerator)。 - zOlive

1

最近我在做类似的事情。对我有用的是使用安装Java时自带的jni.h库(Java\jdk[version]\include),并在Visual Studio中使用C/C++代码创建一个dll。例如:

Test.h

//declare the method you want to implement in c/c++ in the header
//include the jni header
#include <jni.h>
JNIEXPORT void JNICALL Java_Test_print(JNIEnv *, jobject);
//Java_[Class Name]_[Method Name](pointer to JVM, java object);

Test.cpp

extern "C" JNIEXPORT void JNICALL Java_WinampController_printTrackInfo (JNIEnv *env, jobject obj){
    printf("Hey, I'm a java method in c (or not?)\n");
}

然后使用Visual Studio创建一个dll,并在静态块中加载该dll。 我没有尝试过在不编译C / C ++代码为dll的情况下执行此操作,也许还有其他调用C / C ++代码的方法。但这就是你实现它的方式。

Test.java

//declare the same method native inside a class in java
public class Test{
    static {
        System.loadLibrary("Test"); //load the dll
    }
    public native void print();
} //after that you just call test.print() normally

因此,您只需这样做,并使用所有想要的c/c++实现Java方法。

如果您仍然不知道如何操作,请在此处获得启示:

Java本地接口规范-Oracle

Java本地接口-Wikipedia


0

根据您所描述的情况,JNI 可能是最好的选择。您可以将 C++ 应用程序的功能公开为 DLL,以便将其合并到 Java 应用程序中并从中使用。


-2

你可能需要重新考虑你的设计。Java不是这种任务的好选择。Java标准库中没有像Python或Shell中的eval()函数。

你可以使用JNI在C++代码中创建一个Java虚拟机,但是它有点重。还存在如何从Java源代码创建字节码的问题。你将不得不嵌入大量的代码来编译和运行C++中的Java代码。不要这样做。一定有更好的解决方案。

例如,你可以在C++代码和单独的Java代码之间使用一些RPC(SOAP、XML-RPC、Corba)。如果你需要执行类似于eval()的Java调用,可以使用Groovy或Jython(两者都具有eval(),可以访问所有标准Java库并且可以运行常规Java类)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接