2017-09-25 9 views
0

처리 비용을 줄이기 위해 JNI에서 오디오 신호를 처리해야하는 저수준 Android 라이브러리를 개발 중입니다. 같은 오디오 버퍼를 여러 번 참조해야 할 수도 있으므로 구조체의 포인터를 C로 랩핑하여 여러 오디오 버퍼를 동일한 오디오 버퍼에 액세스 할 수 있습니다. 나는 주로 herehere에서 빌린 아이디어를 사용합니다.JNI/Android-NDK에서 포인터를 jlong으로 전달하지 않음()

그러나 예상대로 작동하지 않습니다. 다른 함수가 이전 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 

여기

이 문제를 표시하는 JNI의 예입니다 문제는 메모리 주소 출력이 동일하지 않기 때문에 메모리 주소와 jlong ​​간의 형식 변환입니다. 그러나 변환이 허용되지 않거나 합법적 인 경우 어떻게 발생하는지 모릅니다. (임시적으로) "temp"변수를 덤프 할 때 오류가 발생합니다. 맞습니까?

+0

크기 문제 일 수 있습니다. 포인터는 64 비트이지만 긴 포인터는 32 비트 만 사용하는 경향이 있습니다. 일반적으로 포인터를 저장하려면 긴 길이를 사용해야합니다. –

+0

안녕하세요 게이브, 난 크기 문제도 같아요,하지만 sizeof jlong ​​(= 8 바이트) 인쇄 한 및 특정 Java 긴 것입니다> 8 바이트뿐만 아니라 (예, 긴 testLong = 547383410656L 괜찮습니다.). –

답변

0

문제점을 발견했습니다.

public native int addAudioSamples(byte[] audioToAdd); 

수정 :

public native long addAudioSamples(byte[] audioToAdd); 

자바 나 자동 오버로드 기능의 어떤 종류의 일을하기 위해 꽤 똑똑한 것 같다 놀란 기분이 내 기본 함수 서명은

잘못은 .... 잘못 .

+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. –