【问题标题】:How to access the Java method in a C++ application如何在 C++ 应用程序中访问 Java 方法
【发布时间】:2017-11-10 19:48:02
【问题描述】:

只是一个简单的问题: 是否可以从 c/c++ 调用 java 函数?

【问题讨论】:

    标签: java c++ c


    【解决方案1】:

    是的,你可以,但它有点复杂,并且以反射/非类型安全的方式工作(示例使用比 C 版本更简洁的 C++ api)。在这种情况下,它从 C 代码中创建 Java VM 的实例。如果您的本机代码首先从 Java 调用,则无需构造 VM 实例

    #include<jni.h>
    #include<stdio.h>
    
    int main(int argc, char** argv) {
    
        JavaVM *vm;
        JNIEnv *env;
        JavaVMInitArgs vm_args;
        vm_args.version = JNI_VERSION_1_2;
        vm_args.nOptions = 0;
        vm_args.ignoreUnrecognized = 1;
    
        // Construct a VM
        jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);
    
        // Construct a String
        jstring jstr = env->NewStringUTF("Hello World");
    
        // First get the class that contains the method you need to call
        jclass clazz = env->FindClass("java/lang/String");
    
        // Get the method that you want to call
        jmethodID to_lower = env->GetMethodID(clazz, "toLowerCase",
                                          "()Ljava/lang/String;");
        // Call the method on the object
        jobject result = env->CallObjectMethod(jstr, to_lower);
    
        // Get a C-style string
        const char* str = env->GetStringUTFChars((jstring) result, NULL);
    
        printf("%s\n", str);
    
        // Clean up
        env->ReleaseStringUTFChars(jstr, str);
    
        // Shutdown the VM.
        vm->DestroyJavaVM();
    }
    

    编译(在 Ubuntu 上):

    g++ -I/usr/lib/jvm/java-6-sun/include \ 
        -I/usr/lib/jvm/java-6-sun/include/linux \ 
        -L/usr/lib/jvm/java-6-sun/jre/lib/i386/server/ -ljvm jnitest.cc
    

    注意:为了实现正确的错误处理,应该检查每个方法的返回码(为方便起见,我忽略了这一点)。例如

    str = env->GetStringUTFChars(jstr, NULL);
    if (str == NULL) {
        return; /* out of memory */
    }
    

    【讨论】:

    • +1 例如。可能还想包含设置标题、函数签名等的链接/示例?
    • 您的解决方案很棒,但是如何加载或设置我们创建的类路径例如 HelloWorld.java 即env-&gt;FindClass("HelloWorld");
    • 这对我有用,谢天谢地。我赞成,让我提一下我使用了“-Wl,-rpath,${lib_dir}”,当然没有引号,其中 lib_dir 是 libjvm.so 所在的目录(我使用了 'find /usr/lib/jvm / -name "libjvm.so"',并为我的环境中的实际 jvm lib 目录获取 dirname)。链接(或编译/链接)步骤(即 g++)中的 -Wl,-rpath,${lib_dir} 使您不必在运行时在 LD_LIBRARY_PATH 中指定 lib_dir。
    【解决方案2】:

    【讨论】:

    • 我见过 JNI 曾经从 Java 调用 C++。不知道它也以另一种方式工作。
    • 奇怪,我一直看到它更常用于从 Java 提供对 C++ 库的访问,但它可以双向工作。
    • @CBBailey “提供从 Java 访问 C++ 库”的意思是“从 Java 调用 C++”。不?我觉得你们俩都在说同样的话:“通常用于从 Java 调用 [C++ 代码]”。
    【解决方案3】:

    有很多方法。 Here 是一些想法。此外,商业 Java-COM 桥允许从 c++ 到 java 的 COM 通信(如果您使用的是 Windows)。你也应该看看CNI

    【讨论】:

      【解决方案4】:

      看看invocation API。这使您能够从本机应用程序中加载和启动 JVM,然后从应用程序调用其上的方法。

      简要(来自链接的文档)

      /* 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); 
      

      【讨论】:

        【解决方案5】:

        是的,您可以从 C++ 或 C 调用 Java 函数,但除非您使用 COM 或 CORBA(或我可能不知道的其他第 3 方工具)之类的东西,否则您必须这样做在 JNI 的上下文中。

        从本机代码调用 Java 方法的整个过程在 Sun 的 JNI 指南 pdf 中称为“调用方法”的第 4.2 节的第 4 章中进行了描述,您可以找到 here

        【讨论】:

          【解决方案6】:

          以下函数允许您创建虚拟机。

          JNIEnv* create_vm(JavaVM ** jvm)
          {
              JNIEnv *env;
              JavaVMInitArgs vm_args;
              JavaVMOption options[2];
          
              options[0].optionString = "-Djava.class.path=.";
              options[1].optionString = "-DXcheck:jni:pedantic";  
          
              vm_args.version = JNI_VERSION_1_6;
              vm_args.nOptions = 2;
              vm_args.options = options;
              vm_args.ignoreUnrecognized = JNI_TRUE; // remove unrecognized options
          
              int ret = JNI_CreateJavaVM(jvm, (void**) &env, &vm_args);
              if (ret < 0) printf("\n<<<<< Unable to Launch JVM >>>>>\n");
              return env;
          }
          

          编译著名的Hello World 程序。以下函数尝试调用 HelloWorld 程序的 main 方法。

          int main(int argc, char* argv[])
          {
              JNIEnv* env;
              JavaVM* jvm;
          
              env = create_vm(&jvm);
          
              if (env == NULL) return 1;
          
              jclass myClass = NULL;
              jmethodID main = NULL;
          
          
              myClass = env->FindClass("HelloWorld");
          
          
              if (myClass != NULL)
                  main = env->GetStaticMethodID(myClass, "main", "([Ljava/lang/String;)V");
              else
                  printf("Unable to find the requested class\n");
          
          
              if (main != NULL)
              {
                 env->CallStaticVoidMethod( myClass, main, " ");
          
              }else printf("main method not found") ;
          
          
              jvm->DestroyJavaVM();
              return 0;
          }
          

          现在把 create_vm 函数和 main 函数放到一个 cpp 文件中,包含 jni.h 并编译它。我在 Windows 上使用了 MinGW。

          g++ -D_JNI_IMPLEMENTATION_ -I"C:\Program Files\Java\jdk1.6.0_32\include" -I"C:\Program Files\Java\jdk1.6.0_32\include\win32" hello.cpp -L"C:\Program Files\Java\jre6\bin\client" -ljvm -o hello.exe
          

          执行 现在如果你运行创建的 exe,你会得到一个错误。 jvm.dll not found 。 将 C:\Program Files\Java\jre6\bin\client 放入您的 PATH 环境变量中。现在你可以 运行exe文件。

          注意:不要替换 jvm.dll 文件。

          【讨论】:

            【解决方案7】:

            上面的例子编码完成后,你需要对你的项目做一些配置。

            在 Visual Studio 中将 jvm.lib 链接到您的项目的步骤:

            • 右击项目->属性。
            • 在Properties对话框中,在Linker->Input->AdditionalDependencies区域下添加jvm.lib。
            • 最后写下jvm.lib路径(如“C:\Program Files\Java\jdk1.7.0_60\lib”) Linker->General->AdditionalLibraryDirectories

            完成这些步骤后,您的项目可以链接到 jvm 并正常运行。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-05-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多