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

Posted

技术标签:

【中文标题】将 Java 嵌入到 C++ 应用程序中?【英文标题】:Embed Java into a C++ application? 【发布时间】:2011-09-21 20:39:33 【问题描述】:

我有一个用 C++ 编写的应用程序,我可以通过用 C++ 为它编写插件来扩展应用程序的功能。

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

我读过一些关于 JNI 的文章,但总是有来自使用 Java 类的完整程序的演讲。

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

有没有办法在应用程序运行时(以某种脚本语言)使用 JNI 或类似的东西来编译和评估 Java 代码?

嵌入完成后的示例假想代码:

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 还是只需要一些最小的 VM? 如果您已经确定这种语言必须是 Java,为什么还要说“某种脚本语言”? @MichałŠrajer 这实际上仍然是开放的,Java 和应用程序之间的基本交互对于开始来说会很棒。 @jalf: 应该不需要重新启动应用程序来运行新添加的 Java 代码,我想在 C4D 中编写一个可以直接运行代码的“IDE”跨度> @NiklasR - “基本交互”对于套接字来说听起来不错。 【参考方案1】:

您可以在应用程序中嵌入 JVM。 Oracle 的official reference book 有更多细节。它的概要是:

#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 方法吗?我实际上需要它反过来:) 使用 swig,您可以生成绑定,让您可以从 java 调用 C++。这个问题暗示你想要这种方式。您也可以在一个程序中同时完成这两项工作。 我的两分钱:既然 OP 想要加载插件,我认为他还应该阅读自定义类加载器如何让他读取“插件 jar”。此外,您需要具有本地方法(即 JNI)的 Java 类才能从 Java 调用 C++。【参考方案2】:

您是否希望将 Java 嵌入到 C++ 应用程序中或反之,似乎有些困惑。我会处理每个案例。

    为了将 java 嵌入到 c++ 应用程序中,您可以对 java 程序进行套接字调用。在 java 端,您使用 SocketServer,在 C++ 端,您使用通用套接字层库。这是迄今为止最简单和最具可扩展性的方法。随着您的 java 工作负载不断增加,您不断添加额外的 jvm。部署有点复杂,但是效果很好。

    用于在 java 中嵌入 C++ 应用程序。这很简单。您将 C++ 应用程序编译为共享库并使用 JNI 调用它。

【讨论】:

【参考方案3】:

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

如@awoodland 所述,JNI 调用 API 支持这一点。 Here's a current link, for Java 6/7.

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

为此,您可以使用以下方法之一:

用 C 实现的 Java 本机方法 JNA SWIG

有没有办法在应用程序的同时编译和评估 Java 代码 正在使用 JNI 或任何东西运行(以某种脚本语言) 喜欢吗?

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

【讨论】:

要从 Java 调用 C++,我建议也看看 BridJ + JNAerator。【参考方案4】:

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

测试.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 并在 static 块中加载该 dll。 如果没有在 dll 中编译 c/c++ 代码,我没有尝试过,也许还有另一种调用 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 Native Interface Specification - Oracle

Java Native Interface - Wikipedia

【讨论】:

【参考方案5】:

对于您描述的场景,JNI 可能是最好的方法。您会将 C++ 应用程序的功能公开为一个 DLL,该 DLL 可以合并到 Java 应用程序中并从中使用。

【讨论】:

【参考方案6】:

您可能需要重新考虑您的设计。对于此类任务,Java 不是一个好的选择。 java标准库中没有eval()函数类似于python或shell中的eval()

您可以使用 JNI 在 C++ 代码中创建 java VM,但它有点重。如何从 java 源创建字节码仍然存在问题。您必须嵌入大量代码才能在 C++ 中编译和运行 java 代码。不要那样做。一定有更好的解决方案。

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

【讨论】:

以上是关于将 Java 嵌入到 C++ 应用程序中?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将 C++ 小部件嵌入到 PyQt 应用程序中?

如何将非托管 C++ 表单嵌入到 .NET 应用程序中?

将 Python 嵌入到 C++ 应用程序中,无论是不是安装了 Python(在 Windows 上)

如何将多媒体 HTML/JavaScript 应用程序嵌入到 C++ 代码中

将 Python 3.3 嵌入到 C++ 程序中,同时只能从输入中一次读取一行

是否可以将 perl6 嵌入到 C(或 C++)程序中?