如何在 C++ 应用程序中访问 Java 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/992836/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:58:21  来源:igfitidea点击:

How to access the Java method in a C++ application

javac++c

提问by Hemant

Just a simple question: Is it possible to call a java function from c/c++ ?

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

采纳答案by Michael Barker

Yes you can, but it is a little convoluted, and works in a reflective/non type safe way (example uses the C++ api which is a little cleaner than the C version). In this case it creates an instance of the Java VM from within the C code. If your native called is first being called from Java then there is no need to construct a VM instance

是的,你可以,但它有点复杂,并且以反射/非类型安全的方式工作(示例使用比 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();
}

To compile (on Ubuntu):

编译(在 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

Note: that the return code from each of these methods should be checked in order to implement correct error handling (I've ignored this for convenience). E.g.

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

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

回答by CB Bailey

Yes it is, but you have to do it via JNI: http://java.sun.com/javase/6/docs/technotes/guides/jni/index.html

是的,但你必须通过 JNI 来完成:http: //java.sun.com/javase/6/docs/technotes/guides/jni/index.html

回答by Yishai

There are many ways. Hereare some ideas. In addition, commercial Java-COM bridges allow COM communication from c++ to java (if you are using Windows). You should also look at CNI.

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

回答by Timo Geusch

Yes, you can call a Java function from C++ or C, but unless you're using something like COM or CORBA (or another 3rd-party tool that I'm probably not aware of) you'll have to do this in the context of JNI.

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

The whole procedure to call a Java method from native code is described in Chapter 4 in section 4.2 called "Calling Methods" in Sun's JNI guide pdf, which you can find here.

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

回答by Brian Agnew

Take a look at the invocation API. This enables you to load and start up a JVM from withinyour native application, and then to invoke methods upon it from the application.

查看调用 API。这使您可以加载和启动一个JVM的本地应用程序,然后调用从应用程序后,它的方法。

Briefly (from the linked doc)

简要(来自链接的文档)

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

回答by Sorter

The following function allows you to create the VM.

以下函数允许您创建 VM。

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;
}

Compile the famous Hello Worldprogram. The following function attempts to call the main method of the HelloWorld Program.

编译著名的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;
}

Now put create_vm function and main function into a single cpp file, include jni.h and compile it. I used MinGW on windows.

现在将 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

ExectionNow if you run the created exe, you will get an error. jvm.dll not found. Put C:\Program Files\Java\jre6\bin\clientin your PATH environment variable. Now you can run the exe file.

执行现在,如果您运行创建的 exe,您将收到错误消息。找不到 jvm.dll。放入C:\Program Files\Java\jre6\bin\client您的 PATH 环境变量。现在您可以运行 exe 文件。

Note: Don't displace the jvm.dll file.

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

回答by Mustafa Kemal

After coding above examples, you need to do some configuration on your project.

在对上面的示例进行编码后,您需要对您的项目进行一些配置。

Steps to link the jvm.lib to your project in Visual Studio:

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

  • Right click on the project -> properties.
  • On the Properties dialog box, add jvm.lib under Linker->Input->AdditionalDependencies area.
  • Lastly write jvm.lib path(like "C:\Program Files\Java\jdk1.7.0_60\lib") under Linker->General->AdditionalLibraryDirectories
  • 右键单击项目-> 属性。
  • 在 Properties 对话框中,在 Linker->Input->AdditionalDependencies 区域下添加 jvm.lib。
  • 最后在 Linker->General->AdditionalLibraryDirectories 下写入 jvm.lib 路径(如“C:\Program Files\Java\jdk1.7.0_60\lib”)

After those steps, your project can link to jvm and work well.

在这些步骤之后,您的项目可以链接到 jvm 并且运行良好。