À l'aide de JNI, j'essaie d'écrire une méthode native C++ pour le NDK Android qui effectue un appel à une fonction C définie dans un fichier d'en-tête personnalisé. Cependant, j'obtiens une erreur de référence non définie pour mon appel de fonction C.
Voici mon code C++ qui appelle la fonction C et renvoie son résultat à Java en tant que 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));
}
Voici ma fonction 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";
}
Voici mon code 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)
Apparemment, il semble que la définition de fonction définie dans le fichier d'en-tête personnalisé (gesture_detector.h
) est introuvable. Je pense que cela peut être un problème dans mon fichier Android.mk.
Quelqu'un pourrait-il me dire ce que je fais mal ici?
Une erreur de "référence non définie" provient de l'éditeur de liens . Votre fichier d'en-tête ne satisfait que le compilateur.
Cependant, puisque vous mélangez C et C++, votre problème est probable nom mangling . Fondamentalement, vous devez indiquer au compilateur C++ que la fonction que vous essayez d'appeler a été créée par un compilateur C plutôt que par C++, et n'a donc pas de codes de type d'argument greffés sur son nom. À l'heure actuelle, il ne le sait pas, il essaie donc d'appeler la fonction par un nom décoré de style C++ qui diffère du nom C simple de la fonction dont l'éditeur de liens dispose réellement.
Ajoutez ceci au début de votre fichier gesture_detector.h:
#ifdef __cplusplus
extern "C" {
#endif
Et cela à la fin
#ifdef __cplusplus
}
#endif
Et faites une reconstruction propre.
Si votre véritable logique jni glue est aussi triviale que la version présentée ici, passer à une version C de celle-ci pourrait également être une option - mais attention, la syntaxe jni est différente en C et C++, donc vous ne pouvez pas simplement changer l'extension du fichier .