Ich entwickle eine Low-Level-Android-Bibliothek, die Audiosignale in der JNI verarbeiten muss, um Verarbeitungskosten zu sparen. Da ich möglicherweise mehrmals auf den gleichen Audiopuffer verweisen muss, entscheide ich mich, einen Zeiger einer Struktur beizubehalten, um diesen Audiopuffer in C zu verpacken (so können mehrere C-Funktionen auf denselben Audiopuffer zugreifen). Ich verwende hauptsächlich die von here und here geliehene Idee.Pass-Zeiger als jlong in JNI/Android-NDK funktioniert nicht()
Die Dinge funktionieren jedoch nicht wie erwartet. Mein Programm stürzt nach einer anderen Funktion ab, um auf den Speicher zuzugreifen, der von den vorherigen jni-Aufrufen zugewiesen wurde.
Hier ist das JNI Beispiel, dieses Problem zu zeigen:
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);
}
In Android, ich die JNI-Funktionen wie folgt aufrufen:
public native int addAudioSamples(byte[] audioToAdd);
public native void debugDumpAddAudioRet(long addAudioRet);
int testJNI(byte[] data) {
long ret = addAudioSamples(data);
debugDumpAddAudioRet(ret);
}
Ergebnisse:
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
Ich weiß, Das Problem ist die Typumwandlung zwischen der Speicheradresse und jlong, da die Speicheradressausgaben nicht identisch sind. Allerdings weiß ich nicht, wie es passiert, wenn die Konvertierung nicht erlaubt/legal ist, sollte ich den Fehler bekommen, wenn ich (trivialerweise) die "temp" -Variable ablege, oder?
Möglicherweise ein Größenproblem. Zeiger sind 64 Bit, aber lange sind meist nur 32 Bit. Im Allgemeinen müssen Sie einen langen Long verwenden, um einen Zeiger zu speichern. –
Hallo Gabe, ich denke, es ist auch das Größenproblem, aber ich habe die Größe von jlong (= 8 Bytes) gedruckt und ich bin mir sicher, dass Java lang auch> 8 Byte ist (zB lang testLong = 547383410656L wird in Ordnung sein). –