使用JNI调用Java方法的Objective C

3

有人能向我展示如何从Objective C中调用Java方法吗?

更详细地说,实际上我想做以下两件事:

1)首先从Java端进行调用,到达Objective C端。在此调用期间,我想获取对Java对象的引用。

2)稍后,在Objective C中使用在前一步中获得的引用来调用Java方法。

谢谢


Objective C是C的一个适当超集,因此无论您在C中有什么代码正在工作,只需移植并在ObjC中运行即可。 - Perception
2
你怎么会认为我有C代码呢? :-) - user1216750
其实我是有这个能力的,而且这也是我愿意采取的方法之一。但是我现在手头的C代码比较复杂。其中涉及到很多其他的东西,而且耦合度很高,让我很难跟进并做出相应的修改。另外,我希望整个代码都能保持在Objective C中。 - user1216750
你不需要将C代码改成Objective-C,只需将其放入你的项目中并调用即可。 - danielbeard
1个回答

5
以下内容似乎有效。它基于上面的评论,遵循C示例和此链接。

http://urlgrey.net/?p=121

作为链接所说,不要为环境创建全局变量,而是创建一个指向jvm的全局变量,并创建对您的类的全局引用。
以下是我如何实现第一步: " 1)从Java端进行第一次调用到Objective C。在此期间,我想获取对Java对象的引用。 "
首先在头文件中声明全局变量:
1)jvm:
JavaVM *jvm;

2)Java类:

jclass smartCallbackClass;

3) Java对象:

jobject smartCallbackObject;

在从Java端调用Objective C时,接下来设置这些变量的值。
1)对于JVM:
(*env)->GetJavaVM(env, &jvm);

2)对于对象:

smartCallbackObject = (*env)->NewGlobalRef(env, obj);

3)对于班级:

if (smartCallbackClass == NULL) {
    jclass localRefCls = (*env)->FindClass(env,"com/studyisland/nativelibs/smart/responsesdk/interfaces/thin/SMARTResponseThinClient"); 
    if (localRefCls == NULL) {
        NSLog(@"Unable to create a JNI Java Class reference \n");
    }
    //Create a global reference for JNI Java class
    smartCallbackClass = (*env)->NewGlobalRef(env,localRefCls);

    //Delete the local reference as it is no longer needed
    (*env)->DeleteLocalRef(env, localRefCls);

    //Is the global reference created successfully?
    if (smartCallbackClass == NULL) {
        NSLog(@"Unable to create JNI Java class reference \n");
        return 0;
    }       
}

这是我获取该类代码的链接。

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

现在进行第二步

"2) 接下来,我希望Objective C使用前一步获取的引用来调用Java方法"

要从Objective C回调Java,您需要确保调用是在Java调用Objective C的同一线程上完成的,因此这里是代码。

-(void)classFailedToStop:(SMARTResponseCallBackEventArg*)anArg{
    JNIEnv *env;
    int attach = (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL);
    if(attach == 0){
        (*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_4);
        jmethodID method = (*env)->GetMethodID(env, smartCallbackClass, "callback_onStopClassFailed", "()V");
        (*env)->CallVoidMethod(env, smartCallbackObject, method);
    }
    (*jvm)->DetachCurrentThread(jvm);

}

希望这能有所帮助。

Java如何在Objective-C项目中调用Objective-C?问题不是关于从Objective-C调用Java吗?在你的回答开头,你说“首先从Java端调用Objective-C”? - Lealo
请注意,仅当线程不是Java线程时,才应使用DetachCurrentThread将其与JVM分离。例如,请参见https://dev59.com/E67la4cB1Zd3GeqPcWhf#52342198。 - Hendrik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接