Android 使用 JNI 复制字节缓冲区

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2237147/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:06:19  来源:igfitidea点击:

Copying a byte buffer with JNI

androidjava-native-interfaceandroid-ndk

提问by Daniel Sloof

I've found plenty of tutorials / questions on Stackoverflow that deal with copying char arrays from C/JNI side into something like a byte[] in Java, but not the other way around.

我在 Stackoverflow 上找到了很多教程/问题,这些教程/问题涉及将 C/JNI 端的字符数组复制到 Java 中的字节 [] 之类的东西中,但反过来不行。

I am using a native C library which expects a byte array. I simply want to get data from a byte[] in java, into preferably an unsigned char[] in C.

我正在使用本机 C 库,它需要一个字节数组。我只是想从 java 中的 byte[] 获取数据,最好是 C 中的 unsigned char[] 。

Long story short: What is the best way of copying data from a jBytearray in JNI? Is there any way to detect it's size?

长话短说:从 JNI 中的 jBytearray 复制数据的最佳方法是什么?有没有办法检测它的大小?

采纳答案by Lawrence Dol

Here's a working example I just lifted from my AS/400 JNI library to resolve a native user-queue pointer to test the queue's existence - it copies the queue library and name from a Java byte array (already translated to job's CCSID) into native code and uses it. Take note of the release function calls; these can be changed to copy the native array contents back into the Java byte arrays to move data the other way:

这是我刚刚从我的 AS/400 JNI 库中提取的一个工作示例,用于解析本地用户队列指针以测试队列的存在——它将队列库和名称从 Java 字节数组(已转换为作业的 CCSID)复制到本地代码中并使用它。注意释放函数调用;可以更改这些以将本机数组内容复制回 Java 字节数组,以另一种方式移动数据:

JNIEXPORT jboolean JNICALL Java_com_mycompany_jni400_UserQueue_jniResolve(JNIEnv *jep,jobject thsObj,                
jbyteArray queueLibrary,jbyteArray queueName) {                                                                             
    jbyte            *lib,*nam;                                                                                             
    bool             rtn;                                                                                                   

    thsObj=thsObj;                                                                                                          
    lib=(*jep)->GetByteArrayElements(jep,queueLibrary,0);                                                                   
    nam=(*jep)->GetByteArrayElements(jep,queueName,0);                                                                      
    rtn=(usrq_resolve((byte*)lib,(byte*)nam)!=NULL);                                                                        
    (*jep)->ReleaseByteArrayElements(jep,queueLibrary,lib,JNI_ABORT); /* abort to not copy back contents */                 
    (*jep)->ReleaseByteArrayElements(jep,queueName   ,nam,JNI_ABORT); /* abort to not copy back contents */                 
    if(rtn) { return JNI_TRUE;  }                                                                                           
    else    { return JNI_FALSE; }                                                                                           
    }                                                                                                                       

回答by fadden

The best way to copy a Java byte[] to a native char*is to use the GetByteArrayRegioncall. It does exactly what you want: copies all or part of an array of bytes into a native buffer.

将 Java byte[] 复制到本机的最佳方法char*是使用GetByteArrayRegion调用。它完全符合您的要求:将字节数组的全部或部分复制到本机缓冲区中。

Using GetByteArrayElements/ReleaseByteArrayElementsrequires two calls instead of one, and depending upon the VM's implementation will either pin the byte[] in memory to prevent the GC from moving it, or cause a copy so the GC can freely move the original without disrupting the native code. (This also means that JNI_ABORTwill either "undo" changes or leave them intact, depending on whether the buffer was pinned or copied.)

使用GetByteArrayElements/ReleaseByteArrayElements需要两次调用而不是一次调用,并且根据 VM 的实现将字节 [] 固定在内存中以防止 GC 移动它,或者产生一个副本以便 GC 可以自由移动原始代码而不会破坏本机代码。(这也意味着JNI_ABORT将“撤消”更改或保持不变,具体取决于缓冲区是固定还是复制。)

(See also the "Region Calls" section of the JNI Tipsdocument.)

(另请参阅JNI 技巧文档的“区域调用”部分。)

The GetArrayLengthcall can be used to determine the size of the byte[].

GetArrayLength调用可用于确定byte[].