giorgio salvemini
giorgio salvemini

Reputation: 53

pass an array of mat from native code to java code using CallVoidMethod

I would like to pass an array of arrays calculated from a native method in a Java class. To do this I thought to call the method setTarghet from native code to set each vector field. I think it's a good idea. this is a java class:

public class struttura {


 private int _facetCount;


    public Mat [] VectorTarget;

    public struttura(int facetCount)
    {
        _facetCount = facetCount;


        VectorTarget = new Mat[facetCount];

    }

    public int getFacetCount()
    {
        return _facetCount;
    }

    public void setTarget (int index,Mat value)
    {
        VectorTarget[index]=value;    

    }
}

this is native code

 JNIEXPORT void JNICALL Java_com_example_nonfreejnidemo_NonfreeJNILib_extractorSuTarget(JNIEnv * env, jobject obj, jint nT )
{
   .....

    Mat object[50];

  // read 50 image and put them in object[i]
        for (unsigned int i = 0;i < 50 ;i++) {
            object[i] = imread( files[i], CV_LOAD_IMAGE_GRAYSCALE );
        }

        //Detect the keypoints using SURF Detector
        int minHessian = 500;

        SurfFeatureDetector detector( minHessian );
        std::vector<KeyPoint> kp_object[nT];


        for (unsigned int i = 0;i < nT; i++)
        {
            detector.detect( object[i], kp_object[i] );
        }


        //Calculate descriptors (feature vectors)
        SurfDescriptorExtractor extractor;

        Mat des_object[nT];

        for (unsigned int i = 0;i < nT; i++)
        {
             extractor.compute( object[i], kp_object[i], des_object[i] );

        }
        //-----------------------------------------------------------------------------------------------
        // now begin my problem
    // i want to call method setTarget from java code to map des_object on VectorTarget 
    // and use it on java code.
    // i try something like this but i have some  errors.
    // i now that it is not correct, i do not know how write it.

    for (int index=0; index <50; index++)
    {

               jlong        y  =    (jlong)des_object[index] ;
               jclass cls = env->GetObjectClass(obj);
               jmethodID methodId = env->GetMethodID( cls, "setTarget", "(IJ)V");
               env->CallVoidMethod(obj, methodId,index,y );

     }
        //-----------------------------------------------------------------------------------------------

i want to call method setTarget from java code to map des_object on VectorTarget and use it on java code. i try something like this but i have some errors. i know that it is not correct, i do not know how write it please help me.

Upvotes: 2

Views: 361

Answers (1)

Alex Cohn
Alex Cohn

Reputation: 57183

Your concept has a flow - you cannot pass a C++ instance of class Mat as Java object of class Mat.

On the other hand, you don't need to call Java method just to set an element of a Java Object array.

So, your loop can simply look like

jclass matClass = static_cast<jclass>(env->FindClass("com/example/Mat");
jmethodID matConstructor = env->GetMethodID(matClass, "<init>", "([I)V");
for (int index=0; index<50; index++)
{
    jobject jMatObject = env->NewObject(matClass, matConstructor, des_object[index]);
    env->SetObjectArrayElement( arr, i, jMatObject);
    env->DeleteLocalRef(jMatObject);
}

If your descriptor is not an array of integers, you must prepare the relevant constructor for your Mat Java class.

Note that you can cache both matClass and matConstructor for all calls of your extractorSuTarget() native method.


If you don't need to access the individual elements of des_object, your life is much easier:

public class struttura {

    private int _facetCount;

    public long nativeVectorTarget;

    public struttura(int facetCount)
    {
        _facetCount = facetCount;
    }

    public int getFacetCount()
    {
        return _facetCount;
    }

    private void setTarget(long nativePointer)
    {
        nativeVectorTarget = nativePointer;

    }
}

and in C++,

extern "C" JNIEXPORT void JNICALL Java_com_example_nonfreejnidemo_NonfreeJNILib_extractorSuTarget(JNIEnv * env, jobject obj, jint nT )
{
   .....

    Mat object[50];

  // read 50 image and put them in object[i]
        for (unsigned int i = 0;i < 50 ;i++) {
            object[i] = imread( files[i], CV_LOAD_IMAGE_GRAYSCALE );
        }

        //Detect the keypoints using SURF Detector
        int minHessian = 500;

        SurfFeatureDetector detector( minHessian );
        std::vector<KeyPoint> kp_object[nT];


        for (unsigned int i = 0;i < nT; i++)
        {
            detector.detect( object[i], kp_object[i] );
        }

        //Calculate descriptors (feature vectors)
        SurfDescriptorExtractor extractor;

        Mat* des_object = new Mat[nT]();

        for (unsigned int i = 0;i < nT; i++)
        {
             extractor.compute( object[i], kp_object[i], des_object[i] );

        }
        jclass cls = env->GetObjectClass(obj);
        jmethodID methodId = env->GetMethodID( cls, "setTarget", "(J)V");
        env->CallVoidMethod(obj, methodId, (jlong)des_object);

}

Upvotes: 1

Related Questions