How to access arrays within an object with JNI?

前端 未结 2 814
暗喜
暗喜 2020-12-13 04:05

JNI tutorials, for instance this one, cover quite well how to access primitive fields within an object, as well as how to access arrays that are provided as explicit functio

相关标签:
2条回答
  • 2020-12-13 04:50

    I hope that will help you a little (check out the JNI Struct reference, too):

    // Get the class
    jclass mvclass = env->GetObjectClass( *cls );
    // Get method ID for method getSomeDoubleArray that returns a double array
    jmethodID mid = env->GetMethodID( mvclass, "getSomeDoubleArray", "()[D");
    // Call the method, returns JObject (because Array is instance of Object)
    jobject mvdata = env->CallObjectMethod( *base, mid);
    // Cast it to a jdoublearray
    jdoubleArray * arr = reinterpret_cast<jdoubleArray*>(&mvdata)
    // Get the elements (you probably have to fetch the length of the array as well
    double * data = env->GetDoubleArrayElements(*arr, NULL);
    // Don't forget to release it 
    env->ReleaseDoubleArrayElements(*arr, data, 0); 
    

    Ok here I operate with a method instead of a field (I considered calling a Java getter cleaner) but you probably can rewrite it for the fields as well. Don't forget to release and as in the comment you'll probably still need to get the length.

    Edit: Rewrite of your example to get it for a field. Basically replace CallObjectMethod by GetObjectField.

    JNIEXPORT void JNICALL Java_Test_process(JNIEnv * env, jclass c, jobject jc) {
    
      jclass jcClass = env->GetObjectClass(jc);
      jfieldID iId = env->GetFieldID(jcClass, "i", "I");
    
      // This way we can get and set the "i" field. Let's double it:
      jint i = env->GetIntField(jc, iId);
      env->SetIntField(jc, iId, i * 2);
    
      // The jfieldID of the "a" field (byte array) can be got like this:
      jfieldID aId = env->GetFieldID(jcClass, "a", "[B");
    
      // Get the object field, returns JObject (because Array is instance of Object)
      jobject mvdata = env->GetObjectField (jc, aID);
    
      // Cast it to a jdoublearray
      jdoubleArray * arr = reinterpret_cast<jdoubleArray*>(&mvdata)
    
      // Get the elements (you probably have to fetch the length of the array as well  
      double * data = env->GetDoubleArrayElements(*arr, NULL);
    
      // Don't forget to release it 
      env->ReleaseDoubleArrayElements(*arr, data, 0);
    }
    
    0 讨论(0)
  • 2020-12-13 05:01

    In gcc 6.3 I get a warning saying "dereferencing type-punned pointer will break strict-aliasing rules" from a line like this:

    jdoubleArray arr = *reinterpret_cast<jdoubleArray*>(&mvdata);
    

    But since jdoubleArray is itself a pointer to class _jdoubleArray, there's no need to get the address before casting, and this static_cast works without warnings:

    jdoubleArray arr = static_cast<jdoubleArray>(mvdata);
    
    0 讨论(0)
提交回复
热议问题