JNI教程,例如this一,很好地介绍了如何访问对象中的原始字段,以及如何访问作为显式函数参数提供的数组(即作为{{1}的子类})。但是如何访问 jarray
中字段的Java(原始)数组?例如,我想操作以下Java对象的字节数组:
jobject
主程序可能是这样的:
class JavaClass {
...
int i;
byte[] a;
}
相应的C ++方面将是:
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);
}
我正在考虑使用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
作为其参数。显然我错过了一些东西。有没有办法解决这个问题?
答案 0 :(得分:38)
我希望这会对你有所帮助(也可以查看JNI Struct reference):
// 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清理器),但你可能也可以为字段重写它。不要忘记发布,并且在评论中你可能仍需要获得长度。
编辑:重写您的示例以获取字段。基本上用GetObjectField替换CallObjectMethod。
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);
}
答案 1 :(得分:3)
在gcc 6.3中,我得到一个警告说&#34;解除引用类型惩罚指针会破坏严格别名规则&#34;从这样的一行:
jdoubleArray arr = *reinterpret_cast<jdoubleArray*>(&mvdata);
但是由于jdoubleArray本身是一个指向类_jdoubleArray的指针,因此在转换之前不需要获取地址,并且此static_cast在没有警告的情况下工作:
jdoubleArray arr = static_cast<jdoubleArray>(mvdata);