Копирование байтового буфера с JNI - PullRequest
16 голосов
/ 10 февраля 2010

Я нашел множество учебных пособий / вопросов по Stackoverflow, которые касаются копирования массивов символов со стороны C / JNI в нечто вроде байта [] в Java, но не наоборот.

Я использую нативную библиотеку C, которая ожидает байтовый массив. Я просто хочу получить данные из байта [] в Java, предпочтительно в беззнаковый символ [] в C.

Короче говоря: Каков наилучший способ копирования данных из jBytearray в JNI? Есть ли способ определить его размер?

Ответы [ 2 ]

16 голосов
/ 10 марта 2010

Вот рабочий пример, который я только что поднял из своей библиотеки JNI AS / 400, чтобы разрешить собственный указатель пользовательской очереди для проверки существования очереди - он копирует библиотеку очереди и имя из байтового массива 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; }                                                                                           
    }                                                                                                                       
13 голосов
/ 19 марта 2010

Лучший способ скопировать байт Java [] в собственный char* - это использовать вызов GetByteArrayRegion. Он делает именно то, что вам нужно: копирует весь или часть массива байтов в собственный буфер.

Использование GetByteArrayElements / ReleaseByteArrayElements требует двух вызовов вместо одного, и в зависимости от реализации виртуальной машины либо закрепит байт [] в памяти, чтобы предотвратить его перемещение GC, либо вызовет копию, чтобы GC мог свободно переместить оригинал, не нарушая нативный код. (Это также означает, что JNI_ABORT будет «отменять» изменения или оставлять их без изменений, в зависимости от того, был ли буфер закреплен или скопирован.)

(См. Также раздел «Региональные вызовы» документа JNI Tips .)

Вызов GetArrayLength может использоваться для определения размера byte[].

...