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.
Может ли кто-нибудь сказать мне, что я делаю неправильно здесь?
Ответы
Ответ 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
Здесь вы найдете информацию об этом.