Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass an array of Mats to native code

The native function I want to use requires an array of 7 Mats:

static int nativeCode(cv::Mat &inputImg, cv::Mat bufImgs[7]);

In jni_part I have:

Mat& mRgba = *(Mat*)inRgba;
Mat& bufImgs[7] = *(Mat*)inBufImgs;
nativeCode(mRgba,bufImgs);

In my Java code I'm declaring my fields:

private Mat mRgba;
private Mat[] bufImgs = new Mat[7];

I can call getNativeObjAddr on mRgba, but How do I do the equivalent for the array?

Some background:

I'm using OpenCV, doing live image processing with the camera. The function I'm calling on each frame requires some extra objects. To prevent creating and destroying these objects every frame, I'd like to create them once, and just pass references across each time.

like image 758
fredley Avatar asked Apr 15 '13 09:04

fredley


1 Answers

You have to convert the array of Java object references into a native array of cv::Mat. Since you have a method to get the address of the native object, that's quite simple. You create a native method on the java side:

public class MyClass {
    private Mat mRgba;
    private Mat[] bufImgs = new Mat[7];

    // set the fields and all...
    // ...

    // Call the native method
    private native int callNativeCode();
}

Then on the C/C++ side, you implement callNativeCode like this:

JNIEXPORT jint JNICALL Java_MyClass_callNativeCode(::JNIEnv* env, jobject thisobject)
{
    // Find the required classes
    jclass thisclass = env->GetObjectClass(thisobject);
    jclass matclass = env->FindClass("org/opencv/core/Mat");

    // Get methods and fields
    jmethodID getPtrMethod = env->GetMethodID(matclass, "getNativeObjAddr", "()J");
    jfieldID mrgbafieldid = env->GetFieldID(thisclass, "mRgba", "Lorg/opencv/core/Mat;");
    jfieldID bufimgsfieldid = env->GetFieldID(thisclass, "bufImgs", "[Lorg/opencv/core/Mat;");

    // Let's start: Get the fields
    jobject mrgba = env->GetObjectField(thisobject, mrgbafieldid);
    jobjectArray bufimgsArray = (jobjectArray)env->GetObjectField(thisobject, bufimgsfieldid);

    // Convert the array
    cv::Mat nativeBufImgs[7];
    for (int i = 0; i < 7; i++)
        nativeBufImgs[i] = *(cv::Mat*)env->CallLongMethod(env->GetObjectArrayElement(bufimgsArray, i), getPtrMethod);

    // Get the address for mRgba
    cv::Mat* mrgbaptr = (cv::Mat*)env->CallLongMethod(mrgba, getPtrMethod);

    // We're done! Call the method and return!
    return nativeCode(mrgbaptr, nativeBufImgs);
}
like image 163
main-- Avatar answered Oct 25 '22 22:10

main--