如何使用JNI访问对象中的数组? [英] How to access arrays within an object with JNI?

查看:304
本文介绍了如何使用JNI访问对象中的数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JNI教程(例如)很好地介绍了如何访问原始语言对象中的字段,以及如何访问作为显式函数参数(即jarray的子类)提供的数组.但是,如何访问位于 jobject中的字段的Java(原始)数组?例如,我想对以下Java对象的字节数组进行操作:

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 function arguments (i.e. as subclasses of jarray). But how to access Java (primitive) arrays that are fields within an jobject? For instance, I'd like to operate on the byte array of the following Java object:

class JavaClass {
  ...
  int i;
  byte[] a;
}

主程序可能是这样的:

class Test {

  public static void main(String[] args) {
    JavaClass jc = new JavaClass();
    jc.a = new byte[100];
    ...
    process(jc);
  }

  public static native void process(JavaClass jc);
}

相应的C ++端将是:

The corresponding C++ side would then be:

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");

  // But how do we operate on the array???
}

我本来想使用GetByteArrayElements,但是它想要一个ArrayType作为其参数.显然我缺少了一些东西.有办法吗?

I was thinking to use GetByteArrayElements, but it wants an ArrayType as its argument. Obviously I'm missing something. Is there a way to to this?

推荐答案

希望对您有所帮助(请查看 JNI结构参考):

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); 

好吧,在这里我使用的是方法而不是字段(我考虑过调用Java getter清理程序),但是您可能也可以为字段重写它.不要忘了发布,就像在评论中一样,您可能仍然需要获取长度.

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.

重写您的示例以获取该字段.基本上用GetObjectField代替CallObjectMethod.

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);
}

这篇关于如何使用JNI访问对象中的数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆