Подтвердить что ты не робот

Android NDK/JNI - undefined ссылка на функцию, определенную в пользовательском файле заголовка

Используя JNI, я пытаюсь написать собственный С++-метод для Android NDK, который делает вызов функции C, определенной в пользовательском файле заголовка. Тем не менее, я получаю опорную ошибку undefined для моего вызова функции C.

Вот мой код на С++, который вызывает вызов функции C и возвращает его результат в Java как jstring:

#include <jni.h>

#include "gesture_detector.h"

JNIEXPORT jstring JNICALL Java_com_example_bmtitest_JavaAbstractionLayer_callGestureAnalysis(JNIEnv *env, jobject obj, jfloat previousX, jfloat previousY, jfloat currentX, jfloat currentY) {
    return env->NewStringUTF(gestureAnalysis(previousX, previousY, currentX, currentY));
}

Вот моя функция C:

#include <stdio.h>

#include "gesture_detector.h"

//implemented from gesture_detector.h
const char* gestureAnalysis(float previousX, float previousY, float currentX, float currentY)
{
    float xOffset = currentX - previousX;
    float yOffset = currentY - previousY;

    if(xOffset == 0 && yOffset == 0)
    {
        return "TAP";
    }
    return "0";
}

Вот мой код Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := gestureDetector
LOCAL_SRC_FILES := gestureDetector.c NativeAbstractionLayer.cpp
LOCAL_LDLIBS    := -landroid

include $(BUILD_SHARED_LIBRARY)

По-видимому, кажется, что определение функции, определенное в пользовательском файле заголовка (gesture_detector.h), не найдено. Я думаю, что это может быть проблемой в моем файле Android.mk.

Может ли кто-нибудь сказать мне, что я делаю неправильно здесь?

4b9b3361

Ответ 1

Ошибка "undefined reference" исходит от компоновщика. Ваш файл заголовка удовлетворял только компилятор.

Однако, поскольку вы смешиваете C и С++, ваша проблема, скорее всего, name mangling. В принципе, вам нужно сообщить компилятору С++, что функция, которую вы пытаетесь вызвать, была создана компилятором C, а не С++, и поэтому не имеет кодов типа аргументов, привитых к его имени. Сейчас он этого не знает, поэтому пытается вызвать функцию с помощью декорированного названия стиля С++, который отличается от простого имени C функции, доступной компоновщиком.

Добавьте это в начало файла gesture_detector.h:

#ifdef __cplusplus
extern "C" {
#endif

И это в конце

#ifdef __cplusplus
}
#endif

И выполните чистую перестройку.

Если ваша настоящая логика jni-клея такая же тривиальная, как и представленная здесь версия, переход на версию C тоже может быть опцией - но будьте осторожны, что jni-синтаксис отличается на C и С++, поэтому вы не можете просто изменить расширение файла.

Ответ 2

Просто сделайте свой собственный С++-код между

extern "C" {
    your code
}

Это то, что не всегда обязательно будет работать - как вы можете проверить здесь.

Попробуйте добавить в файл Android.mk:

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

Здесь вы найдете информацию об этом.