Връщане на байт [] от JNI към Java

Всъщност това ми работи, но не правилно. Имам обратно извикване (публикуван в предишен въпрос: Не мога да получа JNIEnv* стойност в произволен контекст), който сега извиква обратно извикване в 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);

Това не е ByteMethod. Това е VoidMethod.

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
Въздишка Наистина не харесвам този начин на програмиране, комбинирането на 2 езика, но разбрах, че наистина сте били прави... Забравих да премахна главната буква A от CallByteMethodA, когато я промених на CallVoidMethod. Вече работи, така че благодаря.. :) - person ThaMe90; 16.05.2011