【问题标题】:Returning jbyteArray from native c in Android在Android中从本机c返回jbyteArray
【发布时间】:2026-01-01 03:55:01
【问题描述】:

我使用原生 c 从音频文件读取数据到 jbyte 指针。现在我想将它作为 jbyteArray 发送到 java。

jbyteArray Java_com_app_audio_player_readData(JNIEnv * env, jobject jobj,jstring readPath)
{

FILE *fin;
const char *inFile= (*env)->GetStringUTFChars(env,readPath,0);
fin = fopen(inFile, "r");

fseek(fin, 0, SEEK_END); // seek to end of file
 int size = ftell(fin); // get current file pointer
fseek(fin, 0, SEEK_SET);

jbyte *data=(jbyte *)malloc(size*sizeof(jbyte));
int charCnt = 0;

charCnt=fread(data, 1, size, fin);


jbyteArray result=(*env)->NewByteArray(env, size);

     //-- I want to convert data to jbyteArray and return it to java    

fclose(fin);
 return result;

}

它是怎么做的?

【问题讨论】:

    标签: android c android-ndk java-native-interface


    【解决方案1】:

    使用SetByteArrayRegion

    charCnt=fread(data, 1, size, fin);
    
    jbyteArray result=(*env)->NewByteArray(env, size);
    
    (*env)->SetByteArrayRegion(env, result, 0, size, data);
    



    也可以使用GetByteArrayElements 例如:

    jboolean isCopy;
    jbyte* rawjBytes = (*env)->GetByteArrayElements(env, result, &isCopy);
    
    //do stuff to raw bytes
    memcpy(rawjBytes, data, size*sizeof(jbyte));
    
    (*env)->ReleaseByteArrayElements(env, result, rawjBytes, 0);
    

    see here 了解有关SetByteArrayRegionGetByteArrayElementsReleaseByteArrayElements 的更多详细信息。


    注意:这个问题可能是this question的特例

    【讨论】:

    • @Roman ~但这里的意图使用memcpydata复制到rawjBytes?! & 演示了SetByteArrayRegion 的替代方案,可以说,大的data 需要动态/增量构造:我们可以使用GetByteArrayElements 来访问jbyteArray 内容;然后使用零值第三个参数调用ReleaseByteArrayElements 确保数据被复制回来(无论底层内存是否被固定)。
    • 噢...对不起,我不明白。还是非常感谢你,对我帮助很大。
    • @Roman ~ 没问题。 &当然可以按照您的建议进行操作:将rawjBytesmemcpy 访问到其他内存位置。所以我很欣赏潜在的混乱&&所以你指出来很好:)
    • 在您的 SetByteArrayRegion() 示例中,我认为您在 args 列表中使用“jbyteArray”,而您的意思是使用“结果”,对吧? (即:使用 var 名称,而不是其类型)
    • @Trent Gray-Donald +1 ~眨眼!想象一下之前没有注意到这一点。大声笑。 〜固定。