使用JNI从Cocoa调用Java类函数 [英] Calling a Java class function from Cocoa with JNI

查看:133
本文介绍了使用JNI从Cocoa调用Java类函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的很努力想办法如何使用JNI从Objective-C调用一个Java函数。

I'm really struggling to figure out how I can call a Java function from Objective-C using JNI.

我应该先说我不知道​​Java的什么,但是我非常熟悉Obj-C。我有一个单一的Java类与单一的方法,我需要从我的应用程序包调用。 jar在Bundle中的Resources文件夹内,我有 NSJavaRoot 设置为内容/资源 NSJavaNeeded ,并且 NSJavaPath 包含2个jar文件的名称(主要一个和一个依赖)。

I should start by saying I don't know anything much about Java but am very familiar with Obj-C. I have a single Java class with a single method that I need to call from my app bundle. The jar is inside the Resources folder in the bundle and I have NSJavaRoot set to Content/Resources, NSJavaNeeded is checked and NSJavaPath contains the names of 2 jar files (main one and one dependency).

我通过调用 JNI_CreateJavaVM 启动虚拟机,然后尝试使用 NSClassFromString 这感觉错了,但是我在我的搜索中找到的唯一方法。我相信这种方法是正确的,当使用已过时的Java桥,但我找不到任何使用JNI的示例或引用。

I'm firing up the VM using a call to JNI_CreateJavaVM and then attempting to find the class using NSClassFromString which feels wrong but is the only method I have found in my search. I believe this method is correct when using the deprecated Java bridge but I cannot find any examples or references that use JNI.

我的Java类看起来像这样:

My Java class looks like this:

package foo;

public class bar {

    public function dostuff() {

    }

}

我需要在应用程序流程中调用 dostuff()

I need to call dostuff() once as part of the app flow. Does anyone have any ideas how to do this?

谢谢,
J

Thanks, J

推荐答案

由于JavaBridge已被弃用,因此您必须使用JNI完成这一切。在MacOS上,您需要将JavaVM.framework添加到您的项目中,并且从您的源文件中,您要查找的标题是:

Since the JavaBridge has been deprecated, you are going to have to do this all with JNI. On MacOS, you'll want to add the JavaVM.framework to your project, and from your source files, the header you're looking for is:

#import <JavaVM/jni.h>

接下来需要设置JavaVM。这可以是不平凡的,取决于你的类路径和其他要求,但你是在正确的轨道,因为这是你用来创建JVM的函数:

Next you need to set up the JavaVM. This can be non-trivial, depending on your classpath and other requirements, but you're on the right track as this is the function you use to create the JVM:

JNI_CreateJavaVM(JavaVM **pJVM, void **pJNIEnv, void *args);

接下来你需要引用你的类foo.bar。这可以使用从JNI_CreateJavaVM传出的pJNIEnv。您将需要调用:

Next you'll want to get a reference to your class foo.bar. This you can do using the pJNIEnv that was passed out from JNI_CreateJavaVM. You'll want to call:

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

假设一切都设置正确,得到你的类的引用。假设foo.bar有一个默认的无参数构造函数,你可以得到一个实例,如下:

Assuming everything is set up right, you'll get back a reference to your class. Assuming for the moment that foo.bar has a default parameterless constructor, you can get an instance of it, like this:

jobject myFooBar = JNIEnv->NewObject(JNIEnv, myClass);



现在您需要获取doStuff方法的methodID。要做到这一点,你需要它的方法签名,你可以通过调用javap获得,像这样:

Now you need to get the methodID of your doStuff method. To do this, you'll need it's method signature, which you can get by calling javap, like this:

% javap -s foo.bar

这将产生如下输出:

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

methodID,你需要调用它。像这样:

Then you can use that to get the methodID, which you'll need to call it. Like so:

jmethodID mid = JNIEnv->GetMethodID(JNIEnv, myClass, "doStuff", "()V");

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

Assuming all these things have gone right, then you can call the method like this:

JNIEnv->CallVoidMethod(JNIEnv, myFooBar, mid);

并且该方法应该被调用。在任何这些阶段之后,您可能想要与VM检查以查看是否有异常。您可以通过执行以下操作检查是否发生异常:

and the method should get called. After any of these stages, you probably want to check with the VM to see if there was an exception. You can check to see if an exception occurred by doing this:

if (JNIEnv->ExceptionCheck(JNIEnv))
{
    // Handle the exception...
}

你想要的实际throwable,你可以使用ExceptionOccurred JNI方法获取它。

If you want the actual throwable, you can get it using the ExceptionOccurred JNI method.

所以,它是最被剥离:你如何调用一个Java方法从Cocoa与JNI。您将需要阅读JNI文档,特别是有关理解全局引用和本地引用之间差异的部分。 (即使你的可可侧引用最后足够长的时间,在它们被创建的范围之外调用。)事实上,有一个关于常见错误和陷阱的章节,其中许多你会碰到。

So, there it is at it's most stripped down: how you call a Java method from Cocoa with JNI. You will want to read up on the JNI docs, espeically the parts about understanding the differences between global and local references. (i.e. making your Cocoa-side references last long enough to be called outside of the scope in which they were created.) In fact, there's a whole chapter on common mistakes and pitfalls, many of which you will hit.

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

祝你好运!

这篇关于使用JNI从Cocoa调用Java类函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆