Получение байтового массива неизвестной длины из хранилища Java - PullRequest
5 голосов
/ 05 августа 2009

Я уже опубликовал вопрос по этому поводу, но в то время у меня еще не было аккаунта. Я получил ответ, но все еще был в замешательстве, и я не могу продолжать эту тему.

Я снова отправляю вопрос вместе со ссылкой на предыдущий разговор.

Возвращение массива символов из Java в строку - JNI

Данные, которые я храню на Java, сериализуются. Я делаю вызов функции Java, используя следующий кусок кода.

В следующем коде предполагается, что символ C совместим с байтом Java, потому что символ Java имеет 2 байта, тогда как символ C имеет 1 байт. Jbyte также является подписанным символом *

    //value will be the serialized data
void store(char* key, char* value, int val_len)

{

    //consider the jclass and methodid are already initialized

    jstring j_key = (*env)->NewStringUTF(env, key);
    jbyteArray j_value = (*env)->NewByteArray(env, val_len);

    (*env)->SetByteArrayRegion(env, j_value, 0, val_len, (jbyte *)value);

    //The store method on java side will save the value (as is) in memory
    (*env)->CallStaticVoidMethod(j_class, store_method, key, value);

    (*env)->ReleaseByteArrayElements(env, j_value, (jbyte *)value, JNI_ABORT);
    (*env)->ReleaseStringUTFChars(env, j_key, key);

}

После сохранения данных я использую другую функцию для извлечения данных из хранилища. В то время я не знаю, какой объем данных я собираюсь получить. Мой API в C, а магазин в Java. Я буду использовать свои функции C для взаимодействия с Java. А также может быть несколько потоков, извлекающих данные из хранилища Java одновременно.

Я делаю вызовы из C в Java, и мой контроль должен вернуться в программу C после получения данных. Я немного запутался в том, как будет работать код. Как я получу указатель на массив (извлеченный из Java), а затем получить его с помощью GetByteArrayElements. Помните, я не знаю размер данных, которые я собираюсь получить заранее, и поэтому не могу создать байтовый массив с помощью функции NewByteArray, а затем заполнить его данными в коде Java.

Ответы [ 2 ]

12 голосов
/ 07 августа 2009

Хорошо, я понял это. Я положу это здесь, чтобы другие тоже могли этим воспользоваться.

Рассмотрим следующий метод Java, который возвращает байтовый массив (просто фиктивный код, без проверок и т. Д.)

public static byte[] GetData(){
    return myStore.getData();
}

и на стороне C вы можете получить байт [] следующим образом

    void get_data()
{       
    int len = 0;
    char* value = NULL;
    /*Consider j_class, and j_methodid are already initialized*/
    jbyteArray j_value = (*env)->CallStaticObjectMethod(env, j_class, j_methodid);

    if(j_value != NULL)
    {
        len = (*env)->GetArrayLength(env, j_value);
        value = (*env)->GetByteArrayElements(env, j_value, NULL);
    }

    /*later on release the resource*/
    (*env)->ReleaseByteArrayElements(env, j_value, value, 0);
}

Я проверил это, и оно работает. Я собираюсь проверить это для двумерного массива сейчас. Я думаю, что это будет то же самое, что только вы получите jobjectArray, и каждый элемент этого массива является jbyteArray.

1 голос
/ 28 апреля 2011

Большое спасибо! Я пытался передать двойной массив из C в Java, а Java, в свою очередь, возвращает обновленный двойной массив в C. Это часть JNI, где я пытаюсь связать код Java с исходным кодом Fortran. Но код Фортрана должен вызвать еще один код Java для некоторых вычислений. Поэтому я делаю Java с C на Fortran на C на Java с использованием JNI. Решение для отправки двойного массива из C в Java и Java, возвращающего двойной массив в C, здесь.

jdoubleArray tempA = (jdoubleArray)(*envG)->NewDoubleArray(envG,3); //create an array with 3 elements to be sent to Java
jdoubleArray tempB = (jdoubleArray)(*envG)->NewDoubleArray(envG,3); //This is will be //assigned to returned java double array
(*envG)->SetDoubleArrayRegion(envG,tempA,0,3,(const jdouble *)arr);//need to send the //tempA array to Java. "arr" is the double array coming to C from Fortran!
int leng = 0;
for (i = 0; i < 1; i++) {
//sending an array "tempA" to Java. Java returns tempB, a double array
tempB = (*envG)->CallObjectMethod(envG, obj_print, id_print,(*A),(*B),(*C),tempA);
   if (tempB != NULL){
   for (k = 0; k < 3; k++){
      leng = (*envG)->GetArrayLength(envG, tempB);
     jdouble* value = (*envG)->GetDoubleArrayElements(envG, tempB, NULL);
      printf("FROM JAVA ARRAY %f\n", value[k]);
     } //end for
   } //end if
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...