How to pass a ArrayList<Mat> from Java to native side(NDK) in opencv for android

android, android-ndk, java, java-native-interface, opencv

Solution

You could build, in Java, an array of long values (getNativeObjAddr() results for all the Mat) and call a native function passing the array.

In JNI, you could access all the long values with GetArrayLength and GetLongArrayElements (which returns a jlong* to the first element).

Use ReleaseLongArrayElements when done.

Problem

In Java side I have `List<Mat> arystrdimages = new ArrayList<Mat>();` subsequently the images read from a folder in external directory are added into the list ``` for(File f : strdimgs) { Mat tempimg = Highgui.imread(f.getAbsolutePath(), CvType.CV_8UC1); arystrdimages.add(tempimg); } ``` In Native jni side I want to access arystrdimages by its reference. For a single Mat object, we can do it by calling `getNativeObjAddr` method, i.e in opencv4android examples for a Mat object the accessing in native side is done as shown below Java ``` private Mat mRgba; ``` call to native side ``` CallNative(mRgba.getNativeObjAddr()); ``` In Native side ``` JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_CallNative(JNIEnv *env, jobject thiz, jlong addrRgba1) { Mat& mRgb = *(Mat*)addrRgba1; } ``` How to do this for `List<Mat>` objects?. EDIT: Implementation of your suggested solution Java side ``` int elems = arystrdimages.size(); Log.v("Matobjdata", "number of Matobject read = " + elems); //Log.v("Matobjdata", "from native = " + ans); long[] tempobjadr = new long[elems]; for (int i=0; i<elems; i++) { Mat tempaddr = arystrdimages.elementAt(i); tempobjadr[i] = tempaddr.getNativeObjAddr(); } Log.v("Matobjdata", "addresselementsinlong arrray = " + tempobjadr.length); int ans = TrainDescriptors(tempobjadr); // Call to native function Log.v("Matobjdata", "from native = " + ans); ``` Native side ``` JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_TrainDescriptors(JNIEnv *env, jobject trainobject, jlongArray traindataaddr) { vector<Mat> trainimgs; jsize a_len = env->GetArrayLength(traindataaddr); jlong *traindata = env->GetLongArrayElements(traindataaddr, 0); for(int k=0; k<a_len; k++) { Mat & newimage=*(Mat*)traindata[k]; trainimgs.push_back(newimage); } // Do the required manipulation on the images; env->ReleaseLongArrayElements(traindataaddr, traindata, 0); return a_len; } ```

Original source