gpt4 book ai didi

java - android jni返回多个变量

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:49:11 34 4
gpt4 key购买 nike

如何从 jni 函数返回多个变量,避免数组 mangaling 的开销?

最佳答案

我可以想出三种不同的方法。

回调

从您的 JNI 代码中调用一个带有多个参数的 Java 方法,在您的 Java 代码中的某处设置一个变量,您可以在从该方法返回时检索该变量。

JNIEXPORT void JNICALL Java_my_package_name_JNIReturnExample_returnWithJavaCallback(JNIEnv *env, jobject javaThis, jfloat param1, jfloat param2)
{
// Get the class of the current calling object
jclass clazz = (*env)->GetObjectClass(env, javaThis);

// Get the method id of the instance method: void javaCallback(float, float) in my.package.name.JNIReturnExample
jmethodID callback = (*env)->GetMethodID(env, clazz, "javaCallback", "(FF)V");

// Calls my.package.name.JNIReturnExample#javaCallback(float, float);
(*env)->CallVoidMethod(env, javaThis, callback, param1, param2);
}

返回一个新的 Java 对象

在JNI中实例化一个Java对象(my.package.name.JNIReturnExample),并返回给Java。

JNIEXPORT jobject JNICALL Java_my_package_name_JNIReturnExample_returnObjectValue(JNIEnv *env, jobject javaThis, jfloat param1, jfloat param2)
{
// Get the class we wish to return an instance of
jclass clazz = (*env)->FindClass(env, "my/package/name/JNIReturnObject");

// Get the method id of an empty constructor in clazz
jmethodID constructor = (*env)->GetMethodID(env, clazz, "<init>", "()V");

// Create an instance of clazz
jobject obj = (*env)->NewObject(env, clazz, constructor);

// Get Field references
jfieldID param1Field = (*env)->GetFieldID(env, clazz, "param1", "F");
jfieldID param2Field = (*env)->GetFieldID(env, clazz, "param2", "F");

// Set fields for object
(*env)->SetFloatField(env, obj, param1Field, param1);
(*env)->SetFloatField(env, obj, param2Field, param2);

// return object
return obj;
}

传递一个 Java 对象作为参数,并设置它的字段

在您的 Java 代码中创建一个 Java 对象的新实例,并将该对象作为参数传递给您的 JNI 函数。

JNIEXPORT void JNICALL Java_my_package_name_JNIReturnExample_setObjectFields(JNIEnv *env, jobject javaThis, jobject obj, jfloat param1, jfloat param2)
{
// Get the class of the input object
jclass clazz = (*env)->GetObjectClass(env, obj);

// Get Field references
jfieldID param1Field = (*env)->GetFieldID(env, clazz, "param1", "F");
jfieldID param2Field = (*env)->GetFieldID(env, clazz, "param2", "F");

// Set fields for object
(*env)->SetFloatField(env, obj, param1Field, param1);
(*env)->SetFloatField(env, obj, param2Field, param2);
}

请注意,无论您决定使用哪种方法,都应该缓存各种 JNI 类型 jclass、jmethodID、jfieldID,因为 JNI 查找操作很慢,而且实际上只需要执行一次。


缓存

在回调方法中缓存 JNI 引用,并使用方法调用它们:

static jclass myCallbackClass;
static jmethodID myCallbackMethod;

/**
* Call this method in JNI_OnLoad
*/
void CacheCallback()
{
// Get a reference to the Callback class
jclass clazz = (*env)->FindClass(env, "my/package/name/JNIReturnExample");

// Store a global reference, since the local one will be freed when returning from the function.
myCallbackClass = (*env)->NewGlobalRef(env, clazz);

// Get a reference to the static callback method
jmethodID callback = (*env)->GetStaticMethodID(env, myCallbackClass, "jniCallback", "(II)V");

// jmethodID doesn't need a NewGlobalRef call
myCallbackMethod = callback;
}

/**
* Call this method in JNI_OnUnload
*/
void ReleaseCallback()
{
(*env)->DeleteGlobalRef(env, myCallbackClass);
myCallbackClass = NULL;

// jmethodIDs are safe to keep without an explicit global reference, for this reason, we don't need to delete the reference either.
myCallbackMethod = NULL;
}

关于java - android jni返回多个变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29043872/

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