Calling a Java class function from Cocoa with JNI

前端 未结 1 822
攒了一身酷
攒了一身酷 2021-01-07 05:07

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

I should start by saying I don\'t know anything much about Java but

相关标签:
1条回答
  • 2021-01-07 06:09

    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>
    

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

    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...
    

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

    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
    

    which should produce output like this:

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

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

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

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

    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/

    Good luck!

    0 讨论(0)
提交回复
热议问题