gpt4 book ai didi

android-ndk - 使用接口(interface)的 JNI 回调到 Java

转载 作者:行者123 更新时间:2023-12-03 22:29:53 27 4
gpt4 key购买 nike

首先,让我列出我能获得的最佳结果。
jni call java method which take a custom java interface as parameter

这不回答我的。让我解释一下我的问题。我想按如下方式调用 NDK。

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

代码如下。

(1) java

public interface Callback<T> {
void success(T result);
}
private native void jniUploadAsync(String imagePath, Callback<String> callback);

jniUploadAsync(file.getAbsolutePath(), new Callback<String>() {
@Override
public void success(final String result) {
Log.v("MyClass: result:: ", result);
}
});

(2)CPP
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);
}

(3) 丙
CallMyCMethod() //please assume that it works. The reason I need void* as the type for completionCallback is because, in ObjC implementation I use this

(4) CP
//Call comes back to imageUploadCallback()

(5) java
//I expect this Log.v("MyClass: result:: ", result); to be executed

请注意,这不是关于如何从 C++ 调用 Java 的基本问题。我要解决的 2 个具体点是,如何调用“回调”以及如何在 Java 接口(interface)实现中调用方法。我已经为 Obj-C 做了这个,它是直截了当的。

最佳答案

(2)
首先,您需要存储对 JavaVM 的引用这样你就可以得到JNIEnv后来从其他线程。此外,您还需要从参数中获取的局部变量中获取新的全局引用(不要忘记在不再需要时删除它,否则会导致内存泄漏)。

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

(4)
使用泛型时,原生端无法知道它们是什么类型,所以无论你在哪里使用 T你应该使用 Object在 JNI/C/CPP 部分

您正在 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();
}

关于android-ndk - 使用接口(interface)的 JNI 回调到 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43045382/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com