Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android ndk 使用接口对Java进行JNI回调_Android Ndk_Java Native Interface - Fatal编程技术网

Android ndk 使用接口对Java进行JNI回调

Android ndk 使用接口对Java进行JNI回调,android-ndk,java-native-interface,Android Ndk,Java Native Interface,首先,让我列出我能得到的最好结果。 这不符合我的要求。让我解释一下我的问题。我想打电话给NDK如下 (1) Java->(2)CPP->(3)C(新线程)->(4)CPP->(5)Java 代码如下 (1) 爪哇 (4) CPP (5) 爪哇 请注意,这不是一个关于如何从C++调用java的基本问题。我想解决的两个具体问题是,如何调用“回调”以及如何在Java接口实现中调用方法。我为Obj-C做了这项工作,它是直接向前的。(2) 首先,您需要存储对JavaVM的引用,以便以后能够从其他线程获取

首先,让我列出我能得到的最好结果。

这不符合我的要求。让我解释一下我的问题。我想打电话给NDK如下

(1) Java->(2)CPP->(3)C(新线程)->(4)CPP->(5)Java

代码如下

(1) 爪哇

(4) CPP

(5) 爪哇

请注意,这不是一个关于如何从C++调用java的基本问题。我想解决的两个具体问题是,如何调用“回调”以及如何在Java接口实现中调用方法。我为Obj-C做了这项工作,它是直接向前的。

(2) 首先,您需要存储对
JavaVM
的引用,以便以后能够从其他线程获取
JNIEnv
。此外,您还需要从从参数中获取的局部变量中获取新的全局引用(当不再需要时,请不要忘记将其删除,否则将导致内存泄漏)

(四) 当使用泛型时,本机端不知道它们是什么类型的,所以无论您在哪里使用
t
,都应该在JNI/C/CPP部分使用
Object

您正在用C启动新线程。如果您愿意从该线程启动回调,则需要将其连接到java虚拟机,然后将其分离。根据我的理解,回调对象只使用一次。在这种情况下,还需要删除对它的全局引用

void imageUploadCallback(char *json, void *completionCallback) {
    JNIEnv* env;
    jvm->AttachCurrentThread(&env, NULL);

    jclass cbClass = env->FindClass("org/winster/test/Callback");
    jmethodID method = env->GetMethodID(cbClass, "success", "(Ljava/lang/Object;)V");
    jstring abcd = env->NewStringUTF("abcd");
    env->CallVoidMethod(completionCallback, method, abcd);

    env->DeleteGlobalRef(completionCallback);
    jvm->DetachCurrentThread();
}

您遇到了什么错误?不清楚
env
imageUploadCallback
中来自何处。很可能需要调用
AttachCurrentThread
。JNI在应用程序中检测到错误:使用了无效的jobject。这是我在尝试调用“回调”时遇到的错误对不起,这没有帮助。当然,我缓存环境;我想这会被理解的。正如所指出的,我在这里试图解决的问题是;当以接口为类型的实例时,如何在Java中调用回调。调用常规类方法并从本机线程调用它们是很容易解决的问题。您不能缓存env它只对该线程有效(对于当前jni调用的持续时间?),您必须从jvm获得它(您可能知道它,但编写了env而不是jvm)。从您的主要帖子上的评论中,我看到了错误:您从jni调用获得的对jobject的引用是本地的,您需要在存储它以供以后使用之前进行全局引用。我更新了关于如何缓存jvm的代码。我现在尝试的一个可能的选择是仅用Java保存回调。但是我必须把“作业项目”从CPP传给C。你知道怎么做吗?我想一个指针可能会对我有所帮助。我还在jni中添加了使用全局引用,我之前忘记了这一点。如果您在评论中提到的
使用无效的jobject
仍然不起作用,则应该是这种情况。2对示例代码的更改。1) 我使用了“&”CallMyCMethod((char*)filePath、&imageUploadCallback、&globalref),而不是(void*);2) 从void*env->CallVoidMethod(static_cast(completionCallback)、callback_mid、jsonString)强制转换回jobject;同一错误“使用无效的jobject”
static JavaVM *jvm;
void imageUploadCallback(char *json, void *completionCallback) {
    JNIEnv *env;
    jint rs = jvm->AttachCurrentThread(&env, NULL);//create JNIEnv from JavaVM    
    jclass cbClass = env->FindClass("org/winster/test/Callback");
    jmethodID method = env->GetMethodID(cbClass, "success", "(Ljava/lang/String;)V");
    env->CallVoidMethod(static_cast<jobject>(completionCallback), method, "abcd");
}

void Java_org_winster_test_MyClass_jniUploadAsync(JNIEnv * env, jobject obj, jstring imagePath, jobject completionCallback) {
    jint rs = env->GetJavaVM(&jvm); //Cache JavaVM here
    CallMyCMethod((char *)filePath, &imageUploadCallback, &completionCallback);
}
CallMyCMethod() //please assume that it works. The reason I need void* as the type for completionCallback is because, in ObjC implementation I use this
//Call comes back to imageUploadCallback()
//I expect this Log.v("MyClass: result:: ", result); to be executed
static JavaVM* jvm = 0;

void Java_org_winster_test_MyClass_jniUploadAsync(JNIEnv * env, jobject obj, jstring imagePath, jobject completionCallback) {
    env->GetJavaVM(&jvm); //store jvm reference for later

    jobject globalref = env->NewGlobalRef(completionCallback);

    CallMyCMethod((char *)filePath, &imageUploadCallback, (void *)globalref);
}
void imageUploadCallback(char *json, void *completionCallback) {
    JNIEnv* env;
    jvm->AttachCurrentThread(&env, NULL);

    jclass cbClass = env->FindClass("org/winster/test/Callback");
    jmethodID method = env->GetMethodID(cbClass, "success", "(Ljava/lang/Object;)V");
    jstring abcd = env->NewStringUTF("abcd");
    env->CallVoidMethod(completionCallback, method, abcd);

    env->DeleteGlobalRef(completionCallback);
    jvm->DetachCurrentThread();
}