2016-08-01 2 views
3

Я пытаюсь написать собственный C-код на Android с помощью NDK. У меня есть функция segment_offline(), которая принимает множество аргументов, включая целочисленный указатель int * num_segments. Я хочу этот указатель, потому что я хочу прочитать значение, назначенное целому числу, которое этот указатель указывает на мою функцию C, которая действует как мой интерфейс JNI. Вот код для segment_offline():Адрес указателя изменяется при передаче функции C ниже уровня JNI

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; 
} 

Функция JNI C, что я написал:

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; 

    } 

Вы видите в приведенном выше коде, который я инициализируется num_segments как int переменной и прохождения адрес этой переменной в функцию, упомянутую выше.

Итак, кажется, что я не могу разглядеть указатель int. Любые предложения по этому поводу. Мне нужен этот указатель, потому что я возвращаю другое значение в качестве возвращаемого значения функции.

+0

Что такое 'seg.num_segments'? Опубликовать полный 'segment_offline()'. – Sergio

+0

Я попробовал напечатать его значение с помощью '% d', и он печатает 1 для меня, который является ожидаемым. – Swapnil

+0

В любом случае, можете ли вы разместить определение 'segment_offline()'? И почему вы используете cast для 'int *'? Функция уже имеет правильный тип возврата. – Sergio

ответ

2

Просто догадаться. Кто-то развращает ваш num_segments перед развратом. Попробуйте напечатать его значение сразу при начале функции, а затем перед сбоем. Также журнал сбоев показывает, что SIGSEGV происходит по адресу 0x60000000, что маловероятно, адрес объекта стека.

EDIT

Также неправильное значение аргумента может быть вызвано вызовом неправильно объявлена ​​функция, то есть если у вас есть вызов функции, которая еще не определен или определен в другом ЕП - вы должны предоставить вперед заявление о том, сообщает компилятору о фактическом списке аргументов и типе возвращаемого значения. Обратите внимание, что C89 допускает неявное объявление функции. В случае, если вы не объявляете функцию - компилятор предполагает, что он имеет тип возврата int и принимает любое количество любых аргументов. See here for details. Обратите внимание, что несоответствие подписи определения и вызова вызывает неопределенное поведение.

P.S. Кроме того, отсутствие форвардной декларации может заставить вас использовать функцию return, поскольку компилятор ожидает, что она будет int.

+0

Я так не думаю, потому что я не использовал эту переменную указателя где-нибудь еще, кроме разыменования. Спасибо за мысль в любом случае. – Swapnil

+0

Просто коррекция. Адрес фактически изменяется, когда я передаю его функции C под слоем JNI. Таким образом, значение в слое JNI: 'Адрес в функции JNI: 0x9e192784' и значение сразу после ввода' segment_offilne() 'is' После ввода функции: 0x60000000'. Я как-то чувствую, что это не правильный способ решить эту проблему. Это? – Swapnil

+0

Звучит как проблема ABI. Есть ли перед JNI-функцией декларация пересылки (или определение) 'segment_offline()'? – Sergio

Смежные вопросы