如何从 JNI 返回一个数组到 Java?

我正在尝试使用机器人 NDK。

有没有一种方法可以将 JNI 中创建的数组(在我的例子中是 int[])返回给 Java?如果是这样,请提供一个 JNI 函数的快速示例。

谢谢

102081 次浏览

如果您已经检查了文档并且仍然有问题,那么这些问题应该是您最初的问题的一部分。在本例中,示例中的 JNI 函数创建了许多数组。外部数组由使用 JNI 函数 NewObjectArray()创建的“ Object”数组组成。从 JNI 的角度来看,二维数组就是一个包含许多其他内部数组的对象数组。

以下 for 循环使用 JNI 函数 NewIntArray()创建 int []类型的内部数组。如果只想返回一个单维 int 数组,那么可以使用 NewIntArray()函数来创建返回值。如果您想创建一个单维的 String 数组,那么您可以使用 NewObjectArray()函数,但是要为该类使用一个不同的参数。

因为你想返回一个整型数组,那么你的代码看起来像这样:

JNIEXPORT jintArray JNICALL Java_ArrayTest_initIntArray(JNIEnv *env, jclass cls, int size)
{
jintArray result;
result = (*env)->NewIntArray(env, size);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
int i;
// fill a temp structure to use to populate the java int array
jint fill[size];
for (i = 0; i < size; i++) {
fill[i] = 0; // put whatever logic you want to populate the values here.
}
// move from the temp structure to the java structure
(*env)->SetIntArrayRegion(env, result, 0, size, fill);
return result;
}

如果有人想知道如何返回 String []数组:

Java 代码

private native String[] data();

本土出口

JNIEXPORT jobjectArray JNICALL Java_example_data() (JNIEnv *, jobject);

本地代码

  JNIEXPORT jobjectArray JNICALL
Java_example_data
(JNIEnv *env, jobject jobj){


jobjectArray ret;
int i;


char *message[5]= {"first",
"second",
"third",
"fourth",
"fifth"};


ret= (jobjectArray)env->NewObjectArray(5,
env->FindClass("java/lang/String"),
env->NewStringUTF(""));


for(i=0;i<5;i++) {
env->SetObjectArrayElement(
ret,i,env->NewStringUTF(message[i]));
}
return(ret);
}

链接: Http://www.coderanch.com/t/326467/java/java/returning-string-array-program-java

简单的解决方案是将数组数据写入一个 C 文件中,然后从 Java 访问该文件

根据提出的问题,第一个答案已经解释了如何通过 jobjectArray 传递 int []。但是这里有一个例子,我们如何返回一个包含数据列表的 jobjectArray。这对于以下情况很有帮助: 例如,当某人需要以2D 格式返回数据,以便用 x 和 y 点画一条线。下面的例子展示了 jobjectArray 如何以以下格式返回数据:

JNI 的 Java 输入:
数组[ x 浮点数的 Arraylist][ y 浮点数的 Arraylist]

JNI 对 java 的输出:
[ x 浮点数的 Arraylist][ y 浮点数的 Arraylist]

    extern "C" JNIEXPORT jobjectArray JNICALL
_MainActivity_callOpenCVFn(
JNIEnv *env, jobject /* this */,
jobjectArray list) {


//Finding arrayList class and float class(2 lists , one x and another is y)
static jclass arrayListCls = static_cast<jclass>(env->NewGlobalRef(env->FindClass("java/util/ArrayList")));
jclass floatCls = env->FindClass("java/lang/Float");
//env initialization of list object and float
static jmethodID listConstructor = env->GetMethodID(arrayListCls, "<init>", "(I)V");
jmethodID alGetId  = env->GetMethodID(arrayListCls, "get", "(I)Ljava/lang/Object;");
jmethodID alSizeId = env->GetMethodID(arrayListCls, "size", "()I");
static jmethodID addElementToList = env->GetMethodID(arrayListCls, "add", "(Ljava/lang/Object;)Z");


jmethodID floatConstructor = env->GetMethodID( floatCls, "<init>", "(F)V");
jmethodID floatId = env->GetMethodID(floatCls,"floatValue", "()F");




//null check(if null then return)
if (arrayListCls == nullptr || floatCls == nullptr) {
return 0;
}


//     Get the value of each Float list object in the array
jsize length = env->GetArrayLength(list);


//If empty
if (length < 1) {
env->DeleteLocalRef(arrayListCls);
env->DeleteLocalRef(floatCls);
return 0;
}


// Creating an output jObjectArray
jobjectArray outJNIArray = env->NewObjectArray(length, arrayListCls, 0);


//taking list of X and Y points object at the time of return
jobject  xPoint,yPoint,xReturnObject,yReturnObject;


//getting the xList,yList object from the array
jobject xObjFloatList = env->GetObjectArrayElement(list, 0);
jobject yObjFloatList = env->GetObjectArrayElement(list, 1);




// number of elements present in the array object
int xPointCounts = static_cast<int>(env->CallIntMethod(xObjFloatList, alSizeId));


static jfloat xReturn, yReturn;
jobject xReturnArrayList = env->NewObject(arrayListCls,listConstructor,0);
jobject yReturnArrayList = env->NewObject(arrayListCls,listConstructor,0);


for (int j = 0; j < xPointCounts; j++) {
//Getting the x points from the x object list in the array
xPoint = env->CallObjectMethod(xObjFloatList, alGetId, j);
//Getting the y points from the y object list in the array
yPoint = env->CallObjectMethod(yObjFloatList, alGetId, j);


//Returning jobjectArray(Here I am returning the same x and points I am receiving from java side, just to show how to make the returning `jobjectArray`)


//float x and y values
xReturn =static_cast<jfloat >(env->CallFloatMethod(xPoint, floatId,j));
yReturn =static_cast<jfloat >(env->CallFloatMethod(yPoint, floatId,j));




xReturnObject = env->NewObject(floatCls,floatConstructor,xReturn);
yReturnObject = env->NewObject(floatCls,floatConstructor,yReturn);


env->CallBooleanMethod(xReturnArrayList,addElementToList,xReturnObject);




env->CallBooleanMethod(yReturnArrayList,addElementToList,yReturnObject);
env->SetObjectArrayElement(outJNIArray,0,xReturnArrayList);
env->SetObjectArrayElement(outJNIArray,1,yReturnArrayList);
__android_log_print(ANDROID_LOG_ERROR, "List of X and Y are saved in the array","%d", 3);


}


return outJNIArray;