我正在開發一個低級Android庫,它需要在JNI中處理音頻信號以節省處理成本。因爲我可能需要多次引用同一個音頻緩衝區,所以我決定保留一個結構的指針來將這些音頻緩衝區包含在C中(因此多個C函數可以訪問相同的音頻緩衝區)。我主要使用從here和here借來的想法。在JNI/Android-NDK中傳遞指針爲jlong不起作用()
但是,事情並不按預期工作。我的程序在另一個函數試圖訪問先前的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」變量時,我會得到錯誤,對嗎?
可能是尺寸問題。指針是64位的,但是長度往往只有32位 - 通常你需要用很長的時間來存儲一個指針。 –
嗨Gabe,我想這也是大小問題,但我確實打印了sizeof jlong(= 8字節),我確信java long也是> 8個字節(例如,long testLong = 547383410656L就可以了)。 –