如何在JNI中将char*转换为jbyteArray,而不需要分配新的内存区域。

huangapple go评论58阅读模式
英文:

How to cast a char* to jbyteArray in JNI whitout malloc a new memory area

问题

我有一段混合了Java和C的代码,我需要将一个Java代码的byte[]传递给C代码,以执行一些计算。我通过在JNI中使用以下代码将byte[]转换为char*:

jboolean is_copy = JNI_TRUE;
char *native_byte_array = (char *) (*env)->GetByteArrayElements(env, byte_array, &is_copy);

我用char类型完成了计算,返回值也是char类型,我想用jbyteArray返回一个值,这样我就可以在Java中将其用作byte[]类型。我尝试在JNI中使用以下代码(env是C的JNIEnv *):

jbyteArray java_buffer = (*env)->NewByteArray(env, buffer_size);

(*env)->SetByteArrayRegion(env, java_buffer, 0, buffer_size, (const jbyte *) native_buffer);

似乎NewByteArray会创建一个新的byte[]实例,而SetByteArrayRegion会将数据复制到新创建的byte[]中。然而,如果我有一个需要转换为byte[]的大型返回值,这样做效率并不高。所以,是否有一种方法可以创建一个jbyteArray实例,而无需分配新的内存,并使它指向char*区域?

英文:

I have a code mixed Java and C, I need pass a byte[] of Java code to C code to complete some calculate.I convert byte[] to char* by using below code in JNI(env is JNIEnv * of C):

jboolean is_copy = JNI_TRUE;
char *native_byte_array = (char *) (*env)->GetByteArrayElements(env, byte_array, &is_copy);

I finished calculate with type char* and the return value has type char* too,I want to return a value with jbyteArray so I can use it in type byte[] in Java.I have try the below code in JNI(env is JNIEnv * of C):

jbyteArray java_buffer = (*env)->NewByteArray(env, buffer_size);

(*env)->SetByteArrayRegion(env, java_buffer, 0, buffer_size, (const jbyte *) native_buffer);

It seems like that NewByteArray will create a new byte[] instance and SetByteArrayRegion will copy data into the new created byte[].
However,it's not efficient if I have a big return value that need to be cast to byte[].
So,is there a way that can create a jbyteArray instance without malloc new memory and make it point to the char* area?

答案1

得分: 1

你可以使用NewDirectByteBuffer。(我知道,它与byte[]不完全相同,但非常接近)
返回:

//做一些操作...
char* result=...;
return (*env)->NewDirectByteBuffer(env, result, buffer_size);

传递:

JNIEXPORT jobject JNICALL Java_Foo_bar(JNIEnv* env,jclass cls, jobject buffer){
  char* bufferPassedFromJava=(*env)->GetDirectBufferAddress(env,buffer);//可能返回NULL
}

这些DirectByteBuffer实际上只是一个围绕长整型(地址)的小包装器,因此您可以在不复制数组的情况下使用它们。

英文:

You could use NewDirectByteBuffer. (I know, it's not the same as a byte[], but it comes quite near)
To return:

//Do something...
char* result=...;
return (*env)->NewDirectByteBuffer(env, result, buffer_size);

To pass:

JNIEXPORT jobject JNICALL Java_Foo_bar(JNIEnv* env,jclass cls, jobject buffer){
  char* bufferPassedFromJava=(*env)->GetDirectBufferAddress(env,buffer);//May return NULL
}

These DirectByteBuffers are, simplified just a small wrapper around a long (The address), so you can use them without copying arrays around

huangapple
  • 本文由 发表于 2020年9月3日 21:21:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/63724576.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定