如何将数组从 JNI 返回到 Java?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1610045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to return an array from JNI to Java?
提问by RyanCheu
I am attempting to use the android NDK.
我正在尝试使用 android NDK。
Is there a way to return an array (in my case an int[]
) created in JNI to Java? If so, please provide a quick example of the JNI function that would do this.
有没有办法将int[]
在 JNI 中创建的数组(在我的情况下是 an )返回到 Java?如果是这样,请提供执行此操作的 JNI 函数的快速示例。
-Thanks
-谢谢
采纳答案by Jherico
If you've examined the documentation and still have questions that should be part of your initial question. In this case, the JNI function in the example creates a number of arrays. The outer array is comprised of an 'Object' array creating with the JNI function NewObjectArray()
. From the perspective of JNI, that's all a two dimensional array is, an object array containing a number of other inner arrays.
如果您已经检查了文档,但仍有一些问题应该是您最初提出的问题的一部分。在这种情况下,示例中的 JNI 函数会创建多个数组。外部数组由使用 JNI 函数创建的“对象”数组组成NewObjectArray()
。从 JNI 的角度来看,这就是一个二维数组,一个包含许多其他内部数组的对象数组。
The following for loop creates the inner arrays which are of type int[] using the JNI function NewIntArray()
. If you just wanted to return a single dimensional array of ints, then the NewIntArray()
function is what you'd use to create the return value. If you wanted to create a single dimensional array of Strings then you'd use the NewObjectArray()
function but with a different parameter for the class.
以下 for 循环使用 JNI 函数创建类型为 int[] 的内部数组NewIntArray()
。如果您只想返回整数的一维数组,那么NewIntArray()
您将使用该函数来创建返回值。如果您想创建一个一维的字符串数组,那么您可以使用该NewObjectArray()
函数,但为该类使用不同的参数。
Since you want to return an int array, then your code is going to look something like this:
由于您想返回一个 int 数组,因此您的代码将如下所示:
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;
}
回答by zajac.m2
if someone would like to know how to return String[] array:
如果有人想知道如何返回 String[] 数组:
java code
代码
private native String[] data();
native export
本土出口
JNIEXPORT jobjectArray JNICALL Java_example_data() (JNIEnv *, jobject);
native code
本机代码
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);
}
from link: http://www.coderanch.com/t/326467/java/java/Returning-String-array-program-Java
来自链接:http: //www.coderanch.com/t/326467/java/java/Returning-String-array-program-Java
回答by Jeyanth
Simple solution is that write the array data in a file from C,and then access the file from Java
简单的解决方案是从 C 中将数组数据写入文件中,然后从 Java 中访问该文件
回答by Paramita
Based on the asked question, this is already explained in the first answer that how can we pass int[] via jobjectArray. But Here is an example how we can return a jobjectArray which contains lists of data. This can be helpful for situations for example: when someone needs to return data in 2D format to draw some line with x and y points. The below example shows how a jobjectArray can return data in the form of following format:
根据提出的问题,这已经在第一个答案中解释过,我们如何通过 jobjectArray 传递 int[]。但这是一个如何返回包含数据列表的 jobjectArray 的示例。这在以下情况下很有帮助:当有人需要以 2D 格式返回数据以绘制一些带有 x 和 y 点的线时。下面的示例显示了 jobjectArray 如何以以下格式返回数据:
Java input to the JNI:
Array[Arraylist
of x float points][Arraylist
of y float points]
JNI 的 Java 输入:
数组[ Arraylist
x 个浮点数][ Arraylist
y 个浮点数]
JNI output to java:jobjectArray
[Arraylist
of x float points] [Arraylist
of y float points]
JNI 输出到 java:jobjectArray
[ Arraylist
x 个浮点数] [ Arraylist
y 个浮点数]
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;