在JNI / Android-NDK中将指针作为jlong​​传递不起作用()

时间:2017-09-25 20:46:54

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

我正在开发一个低级Android库,需要在JNI中处理音频信号以节省处理成本。由于我可能需要多次引用相同的音频缓冲区,因此我决定保留一个结构的指针以将这些音频缓冲区包装在C中(因此多个C函数可以访问相同的音频缓冲区)。我主要使用从herehere借来的想法。

然而,事情并没有像预期的那样发挥作用。我的程序在另一个函数尝试访问先前jni调用分配的内存后崩溃。

以下是显示此问题的JNI示例:

struct AddAudioRet{
    int chCnt;
    int traceCnt;
    int sampleCnt;
    float ***data; // data[chIdx][traceIdx][sampleIdx]; -> reverse order of the Matlab data structure
};
extern "C" jlong Java_XXX_XXX_addAudioSamples(JNIEnv *env, jobject obj, jbyteArray audioToAdd) {
    // some processing codes
    AddAudioRet *ret;
    ret = (AddAudioRet *)malloc(sizeof(AddAudioRet));
    ret->chCnt = ps->recordChCnt; // 2
    ret->traceCnt = repeatToProcess; // 3
    ret->sampleCnt = as->signalSize; // 2400
    jlong retLong = (jlong)ret;
    mylog("retLong (jlong) = %ld", retLong);
    AddAudioRet *temp = (AddAudioRet *)retLong;
    mylog("temp's chCnt %d, traceCnt %d, sampleCnt = %d", temp->chCnt, temp->traceCnt, temp->sampleCnt);
    return retLong; // return the memory address of the ret structure
}

extern "C" void Java_XXX_XXX_debugDumpAddAudioRet(JNIEnv *env, jobject obj, jlong addAudioRet) {
    debug("addAudioRetLong = %ld", addAudioRet);
    debug("ret's chCnt %d, traceCnt %d, sampleCnt = %d", r->chCnt, r->traceCnt, r->sampleCnt);
}

在Android中,我称之为JNI函数:

public native int addAudioSamples(byte[] audioToAdd);
public native void debugDumpAddAudioRet(long addAudioRet);
int testJNI(byte[] data) {
    long ret = addAudioSamples(data);
    debugDumpAddAudioRet(ret);
}

结果:

retLong (jlong) = 547383410656
temp's chCnt 2, traceCnt 3, sampleCnt = 2400
// *** dumped by the debug check ***
addAudioRetLong = 1922564064
ret's chCnt 55646750, traceCnt 82374663, sampleCnt = 1831675530

我知道问题是内存地址和jlong​​之间的类型转换,因为内存地址输出不相同。但是,我不知道它是如何发生的,如果转换不允许/合法,我应该在我(通常)转储“temp”变量时得到错误,对吧?

1 个答案:

答案 0 :(得分:0)

我发现了问题。我的本机功能签名是错误的....

错:

public native int addAudioSamples(byte[] audioToAdd);

正确:

public native long addAudioSamples(byte[] audioToAdd);

感到非常惊讶,Java似乎非常聪明,可以帮助我自动执行某种函数重载。