2016-08-01 35 views
3

Ich versuche, nativen C-Code in Android mit NDK zu schreiben. Ich habe eine Funktion segment_offline(), die viele Argumente einschließlich eines ganzzahligen Zeigers int * num_segments aufnimmt. Ich will diesen Zeiger, weil ich den Wert lesen möchte, der dem Integer zugewiesen ist, auf den der Zeiger in meiner C Funktion zeigt, die als meine JNI-Schnittstelle fungiert. Hier ist der Code für segment_offline():Die Adresse des Zeigers ändert sich, wenn sie an eine C-Funktion unterhalb der JNI-Ebene übergeben wird

int * segment_offline(const SEGMENT_DATATYPE *x, const int num_samples_x, const float *svara_cents, const int *svara_lengths, const int num_svaras, const int type, const int hop_size, const float tonic, int *num_segments) { 

int i; 

// using DTW ... 
if (0 == type) { 

    filtered_samples_t fns; 

    // removing the negative frequencies in Hz. 
    filter_negative_samples(x, num_samples_x, &fns); 

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After filter_negative_samples\n"); 

    // converting the Hz to Cents 
    convert_pitch_to_cents(fns.arr_filtered, fns.len, tonic); 

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After convert_pitch_to_cents\n"); 

    //print_double_array(fns.arr_filtered, fns.len); 
    segments_t seg = segment_offline_dtw(fns.arr_filtered, fns.len, svara_cents, svara_lengths, num_svaras, hop_size); 

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After segment_offline_dtw\n"); 

    int * ret_segments = (int *) malloc(sizeof(seg.num_segments)); 

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After allocating memory to ret_segments\n"); 

    // setting the value of the number of segments in the pointer that would be referred. 
    // ########## I get a segmentation fault here ######### 
    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "The number of segments are: %d\n", seg.num_segments); 
    *num_segments = seg.num_segments; 

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After assigning the number of segments: %d\n", *num_segments); 

    for (i = 0;i < seg.num_segments * 2; i++) { 
     ret_segments[i] = fns.original_indices[seg.segments_pos[i]]; 
     printf("%d, ", ret_segments[i]); 
    } 
    printf("\n"); 

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "Returning from segment_offline\n"); 

    return ret_segments; 
} 

Die JNI C-Funktion, die ich geschrieben habe, ist:

JNIEXPORT jintArray JNICALL Java_com_camut_audioiolib_dsp_DSPAlgorithms_segmentOffline 
    (JNIEnv *env, jclass cls, jdoubleArray x, jint numSamples, jfloatArray svaraCents, 
    jintArray svaraLengths, jint numSvaras, jint type, jint hopSize, jfloat tonic) { 

    jdouble *xDouble = (*env)->GetDoubleArrayElements(env, x, NULL); 
    jfloat *svaraCentsFloat = (*env)->GetFloatArrayElements(env, svaraCents, NULL); 
    jint *svaraLengthsInt = (*env)->GetIntArrayElements(env, svaraLengths, NULL); 

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "The size of the type tonic is: %d", sizeof(tonic)); 

    int num_segments; 

    int * segments = (int *) segment_offline(xDouble, numSamples, svaraCentsFloat, svaraLengthsInt, 
     numSvaras, type, hopSize, tonic, &num_segments); 

    if (NULL == segments) { 
     return NULL; 
    } 

    // releasing the allocated memories ... 
    (*env)->ReleaseDoubleArrayElements(env, x, xDouble, JNI_ABORT); 
    (*env)->ReleaseFloatArrayElements(env, svaraCents, svaraCentsFloat, JNI_ABORT); 
    (*env)->ReleaseIntArrayElements(env, svaraLengths, svaraLengthsInt, JNI_ABORT); 

    return NULL; 

    } 

Sie im obigen Code sehen, dass ich die num_segments als int Variable initialisiert und Weitergabe der Adresse dieser Variable zu der oben genannten Funktion.

So, es scheint, dass ich nicht in der Lage bin, den int Zeiger zu deaktivieren. Irgendwelche Vorschläge dazu. Ich brauche diesen Zeiger, weil ich einen anderen Wert als Rückgabewert meiner Funktion zurückgebe.

+0

Was "seg.num_segments" ist? Vervollständige 'segment_offline()'. – Sergio

+0

Ich habe versucht, seinen Wert mit '% d' zu drucken und es druckt 1 für mich, was irgendwie erwartet wird. – Swapnil

+0

Wie auch immer, könnten Sie 'segment_offline()' Definition posten? Und warum benutzt du Cast zu 'int *'? Die Funktion hat bereits den richtigen Rückgabetyp. – Sergio

Antwort

2

Nur eine Vermutung. Jemand korrumpiert Ihre num_segments vor dem Löschen. Versuchen Sie, den Wert sofort bei Funktionsbeginn und dann vor der Abbruchlinie auszudrucken. Auch Crash-Log zeigt, dass SIGSEGV auf Adresse 0x60000000 auftritt, das ist unwahrscheinlich, eine Adresse des Stack-Objekts.

EDIT

Auch falsche Argument Wert kann durch Aufruf verursacht werden Funktion falsch deklariert, dh wenn Sie anrufen müssen funktionieren, dass noch nicht oder in einer anderen Übersetzungseinheit definiert definiert ist - müssen Sie Erklärung liefern vor, dass teilt dem Compiler die tatsächliche Argumentliste und den Rückgabetyp mit. Beachten Sie, dass C89 implizite Funktionsdeklaration erlaubt. Falls Sie die Funktion nicht deklarieren, erwartet der Compiler, dass er den Rückgabetyp int hat und eine beliebige Anzahl von Argumenten akzeptiert. See here for details. Beachten Sie, dass die fehlende Übereinstimmung von Definitions- und Anrufsignaturen zu undefiniertem Verhalten führt.

P.S. Auch das Fehlen der Vorwärtsdeklaration kann dazu führen, dass Sie die Rückgabe der Funktion erzwingen, da der Compiler erwartet, dass es int ist.

+0

Ich glaube nicht, weil ich diese Zeigervariable nicht anders als Dereferenzierung verwendet habe. Danke für den Gedanken sowieso. – Swapnil

+0

Nur eine Korrektur. Die Adresse wird tatsächlich geändert, wenn ich sie an die C-Funktion unterhalb der JNI-Ebene übergebe. So ist der Wert in der JNI-Schicht: 'Adresse in der JNI-Funktion: 0x9e192784' und der Wert unmittelbar nach der Eingabe von' segment_offilne() 'ist' Nach nur Eingabe der Funktion: 0x60000000'. Ich fühle irgendwie, dass dies nicht der richtige Weg ist, um dieses Problem zu lösen. Ist es? – Swapnil

+0

Klingt wie ABI-Problem. Gibt es eine Forwarding-Deklaration (oder Definition) von 'segment_offline()' vor der JNI-Funktion? – Sergio