使用JNI从Cocoa调用Java类函数

JWo*_*ood 2 java java-native-interface xcode cocoa objective-c

我真的很难弄清楚如何使用JNI从Objective-C调用Java函数.

我应该首先说我对Java知之甚少,但对Obj-C非常熟悉.我有一个Java类,我需要从我的应用程序包中调用一个方法.jar位于bundle中的Resources文件夹中,我已经NSJavaRoot设置Content/Resources,NSJavaNeeded检查并NSJavaPath包含2个jar文件的名称(主要的一个和一个依赖项).

我正在使用调用来启动虚拟机JNI_CreateJavaVM,然后尝试查找使用NSClassFromString哪个感觉错误的类,但这是我在搜索中找到的唯一方法.我相信这个方法在使用已弃用的Java桥时是正确的,但我找不到任何使用JNI的示例或引用.

我的Java类看起来像这样:

package foo;

public class bar {

    public function dostuff() {

    }

}
Run Code Online (Sandbox Code Playgroud)

我需要dostuff()在app流程中调用一次.有没有人有任何想法如何做到这一点?

谢谢,J

ipm*_*mcc 12

由于JavaBridge已被弃用,您将不得不使用JNI完成所有操作.在MacOS上,您需要将JavaVM.framework添加到项目中,并且从源文件中,您要查找的标题是:

#import <JavaVM/jni.h>
Run Code Online (Sandbox Code Playgroud)

接下来,您需要设置JavaVM.这可能是非常重要的,具体取决于您的类路径和其他要求,但您是在正确的轨道上,因为这是您用于创建JVM的函数:

JNI_CreateJavaVM(JavaVM **pJVM, void **pJNIEnv, void *args);
Run Code Online (Sandbox Code Playgroud)

接下来,您将要获得对您的类foo.bar的引用.这可以使用从JNI_CreateJavaVM传递的pJNIEnv来完成.你想打电话:

jclass myClass = JNIEnv->FindClass(JNIEnv, "foo/bar"); // Note the slashes replacing the dots...
Run Code Online (Sandbox Code Playgroud)

假设一切设置正确,您将获得对您班级的引用.假设foo.bar目前有一个默认的无参数构造函数,你可以得到它的一个实例,如下所示:

jobject myFooBar = JNIEnv->NewObject(JNIEnv, myClass);
Run Code Online (Sandbox Code Playgroud)

现在您需要获取doStuff方法的methodID.要做到这一点,你需要它的方法签名,你可以通过调用javap获得,如下所示:

% javap -s foo.bar
Run Code Online (Sandbox Code Playgroud)

应该产生这样的输出:

Compiled from "bar.java"
public class foo.bar extends java.lang.Object{
public foo.bar();
  Signature: ()V
public void doStuff();
  Signature: ()V
}
Run Code Online (Sandbox Code Playgroud)

然后你可以用它来获取你需要调用它的methodID.像这样:

jmethodID mid = JNIEnv->GetMethodID(JNIEnv, myClass, "doStuff", "()V");
Run Code Online (Sandbox Code Playgroud)

假设所有这些事情都正确,那么你可以这样调用方法:

JNIEnv->CallVoidMethod(JNIEnv, myFooBar, mid);
Run Code Online (Sandbox Code Playgroud)

并且应该调用该方法.在任何这些阶段之后,您可能希望检查VM以查看是否存在异常.您可以通过执行以下操作来检查是否发生了异常:

if (JNIEnv->ExceptionCheck(JNIEnv))
{
    // Handle the exception...
}
Run Code Online (Sandbox Code Playgroud)

如果你想要实际的throwable,你可以使用ExceptionOccurred JNI方法获得它.

所以,它最简单的就是:如何使用JNI从Cocoa调用Java方法.您将需要阅读JNI文档,特别是有关理解全局和本地引用之间差异的部分.(即使你的Cocoa端引用的持续时间足以在创建它们的范围之外调用.)事实上,有一整章关于常见的错误和陷阱,其中很多都会被击中.

http://java.sun.com/docs/books/jni/

祝好运!