Возврат byte[] из JNI в Java

На самом деле у меня это работает, просто не правильно. У меня есть обратный вызов (опубликовано в предыдущем вопросе: Невозможно получить JNIEnv* value в произвольном контексте), который теперь вызывает обратный вызов на уровне Java... Единственная проблема заключается в типе данных, возвращаемом обратным вызовом. В моем коде Java при отладке я вижу, что тип того, что обратный вызов передает в Java, имеет тип class [B вместо типа byte[], который я ожидаю.

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

Обратный вызов в Java:

public void enqueueAudio(byte[] audioData){
    if(audioData != null){
        mWriteQueue.offer(audioData);
    }
}

Обработка очереди:

private void writeToFile(String file){
    int totalNumOfBytes = 0;
    byte[] dataFromQueue = new byte[0];
    byte[] temp;
    for(byte[] data : mWriteQueue){
        temp = dataFromQueue;
        dataFromQueue = new byte[temp.length + data.length];
        System.arraycopy(temp, 0, dataFromQueue, 0, temp.length);
        System.arraycopy(data, 0, dataFromQueue, temp.length, data.length);
        totalNumOfBytes += data.length;
    }
    // Write the total byte[] to the specified file.
    mFileHandler.write(file, dataFromQueue);
    updateUI("Number of bytes written to " + file + " : " + totalNumOfBytes + "\n");
}

Как видите, я предполагаю, что очередь заполнена byte[], а не class [B, что приводит к исключениям приведения классов...

Итак, правильно ли, что нативный код возвращает class [B вместо byte[]?

Для полноты, вот метод на C:

void recorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context){
    SLresult result;
    JNIEnv* env;
    jbyteArray data;
    (*javaVM)->AttachCurrentThread(javaVM, &env, NULL);
    if(env == NULL){
        LOG_ERROR("Could not get JNIEnv*");
        return;
    }
    data = (*env)->NewByteArray(env, MAX_PACKET_SIZE);
    if(data == NULL){
        LOG_ERROR("No memory could be allocated for buffer");
        return;
    }
    (*env)->SetByteArrayRegion(env, data, 0, MAX_PACKET_SIZE, recorderBuffer);
    (*env)->CallByteMethodA(env, javaObject, javaCallbackMID, data);
    (*env)->DeleteLocalRef(env, data);
    result = (*bq)->Enqueue(bq, recorderBuffer,
                            RECORDER_FRAMES * sizeof(jbyte));
    checkError(result, "Unable to enqueue new buffer");
    (*javaVM)->DetachCurrentThread(javaVM);
}

person ThaMe90    schedule 16.05.2011    source источник
comment
Извините, моя ошибка xD Не знаю, почему я добавил этот тег... Теперь он удален...   -  person ThaMe90    schedule 16.05.2011


Ответы (1)


На самом деле у меня это работает, просто не правильно.

Это противоречие в терминах.

  (*env)->CallByteMethodA(env, javaObject, javaCallbackMID, data);

Это не байтовый метод. Это метод пустоты.

person user207421    schedule 16.05.2011
comment
javaCallbackMID — это идентификатор метода enqueueAudio в Java, который был получен вызовом javaCallbackMID = (*env)->GetMethodID(env, javaClass, "enqueueAudio", "([B)V");. Я использую его только для вызова метода Java с параметром byte[], который не передается ему при вызове... - person ThaMe90; 16.05.2011
comment
Однако это все еще не решает проблему... Проблема не в том, что метод Java не вызывается, он вызывается с неправильным типом параметра... - person ThaMe90; 16.05.2011
comment
Вздох Мне действительно не нравится этот способ программирования, то есть объединение двух языков, но я обнаружил, что вы действительно были правы... Я забыл удалить заглавную букву A из CallByteMethodA, когда я изменил ее на CallVoidMethod. Теперь это работает, так что спасибо .. :) - person ThaMe90; 16.05.2011