2017-09-25 19 views
0

処理コストを節約するために、JNIでオーディオ信号を処理する必要がある低レベルのAndroidライブラリを開発しています。私は同じオーディオバッファを複数回参照する必要があるかもしれないので、これらのオーディオバッファをCでラップする構造体のポインタを保持することにしました(複数のC関数が同じオーディオバッファにアクセスできるようにします)。私は主にherehereから借りたアイデアを使用します。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); 
} 

、私はこのような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"変数をダンプするときにエラーを取得する必要がありますか、わからない?

+0

おそらくサイズの問題です。ポインタは64ビットですが、長い間は32ビットしか使わない傾向があります。通常、ポインタを格納するのに長いlongを使用する必要があります。 –

+0

こんにちはGabe、私はそれもサイズの問題だと思うが、私はsizeof jlong​​(= 8バイト)を印刷して、私は確かにJavaの長さ> 8バイトです(例えば、長いtestLong = 547383410656Lはokになります)。 –

答えて

0

問題が見つかりました。私のネイティブ関数のシグネチャが間違っている....

間違っ:

public native int addAudioSamples(byte[] audioToAdd); 

正しい:

public native long addAudioSamples(byte[] audioToAdd); 

は、Javaは私が自動的にオーバーロードする機能のいくつかの種類を行う助けるためにかなりスマート思えるほど驚い感じます。

+0

実際には、 'extern" C "jlong​​ Java_XXX_XXX_addAudioSamples(JNIEnv * env、jobject obj、jbyteArray audioToAdd)'に対して 'native int addAudioSamples(String audioToAdd)'を宣言すれば、Javaはあなたを捕まえません。ただし、オーバーロードされたネイティブメソッドを宣言する方法はありますが、https://stackoverflow.com/a/45024076/192373。 –

関連する問題