2016-09-14 1 views
0

Je suis en train de modifier ce tutoriel pour inclure une bibliothèque C préconstruits dans mon projet Android Studio (ie. Ne pas utiliser le plugin Gradle expérimental) http://kvurd.com/blog/compiling-a-cpp-library-for-android-with-android-studio/éditeur de liens NDK-build Android ne parvient pas à trouver la fonction de bibliothèque préconstruite

La bibliothèque lui-même provient d'un client qui ne révélera pas le code source, donc je n'ai aucun contrôle sur cette partie du processus de construction, mais ils suivent déjà le même tutoriel.

La construction du projet, la bibliothèque de chargement fonctionne et le lien NDK (/jni/my-wrapper.c) fonctionne correctement, jusqu'à ce que j'essaie d'appeler la fonction de bibliothèque réelle définie dans mon en-tête de pré-construction. L'erreur que je reçois est:

$ ndk-build 
[arm64-v8a] Compile  : my-wrapper <= my-wrapper.c 
[arm64-v8a] SharedLibrary : libmy-wrapper.so 
/Users/me/AndroidStudioProjects/MyProject/app/obj/local/arm64-v8a/objs/my-wrapper/my-wrapper.o: In function `Java_com_my_project_SignInActivity_CallFunction': 
/Users/me/AndroidStudioProjects/MyProject/app/jni/my-wrapper.c:44: undefined reference to `MyFunction' 
collect2: error: ld returned 1 exit status 
make: *** [/Users/me/AndroidStudioProjects/MyProject/app/obj/local/arm64-v8a/libmy-wrapper.so] Error 1 

Voici mon Android.mk:

LOCAL_PATH := $(call my-dir) 

# static library info 
include $(CLEAR_VARS) 
LOCAL_MODULE := libMyLib 
LOCAL_MODULE_FILENAME := libMyLib 
LOCAL_SRC_FILES := ../prebuild/libMyLib.a 
LOCAL_EXPORT_C_INCLUDES := ../prebuild/include 
include $(PREBUILT_STATIC_LIBRARY) 

# wrapper info 
include $(CLEAR_VARS) 
LOCAL_C_INCLUDES += ../prebuild/include 
LOCAL_MODULE := my-wrapper 
LOCAL_SRC_FILES := my-wrapper.c 
LOCAL_STATIC_LIBRARIES := libMyLib 
include $(BUILD_SHARED_LIBRARY) 

Et malib.h (notez que foobar() fonctionne bien comme il est dans l'en-tête, mais aussi longtemps que je « m appeler MyFunction à partir de mon-wrapper.c le NDK-build échoue):

#include <math.h> 
#include <setjmp.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int MyFunction(some stuff); 
int foobar(){return 1;}; 

Enfin, ma-wrapper.c:

#include <MyLib.h> 

jbyte Java_com_my_project_SignInActivity_MyFunction(JNIEnv *env, jobject thiz, some other stuff){ 

// return MyFunction(some other stuff which I cast to C types); //linker fails if uncommented 

    return foobar(); //works fine 
} 
+1

Etes-vous sûr que MyFunction existe réellement dans la bibliothèque? Puisque vous n'avez pas accès au code source, cela vaut probablement la peine de vous en assurer. Vous pouvez le vérifier en utilisant l'outil 'nm' inclus dans le NDK Android. –

+0

'nm libMyLib.a' donne' 0000458c T _Z12MyFunctionP9my_structPhS1_S1_' - donc on dirait qu'il est là sauf s'il y a de la subtilité qui me manque – Peter

Répondre

1

C'est un nom C++ tronqué. Vous ne pouvez l'utiliser à partir de C++, pas de C.

Si vous avez vraiment besoin de l'appeler de C, vous pourriez être en mesure de le faire comme ceci:

extern int _Z12MyFunctionP9my_structPhS1_S1_(/* whatever the function args are */); 

jbyte Java_com_my_project_SignInActivity_MyFunction(
     JNIEnv *env, jobject thiz, some other stuff) { 
    return _Z12MyFunctionP9my_structPhS1_S1_(args); 
} 

Cela dépend du code » re appel étant compatible en tant que tel (si c'est le cas, vous devriez demander au client de construire leurs API comme extern "C").

Je vous recommande vraiment de simplement déplacer votre code en C++.

+0

Incroyable! Le client insiste sur le fait que c'est une bibliothèque C - est-il possible qu'ils aient compilé par erreur une source C pour transformer les noms en C++, en suivant aveuglément l'étape 1 de http://kvurd.com/blog/compiling-a-cpp-library- pour-android-avec-android-studio /? Y aurait-il des effets secondaires pour moi simplement en faisant passer le code de l'encapsuleur en C++, auquel cas je devrais y retourner et demander de construire le C lib correctement. Désolé pour les questions de base, un développeur C++ je ne suis pas! – Peter

+0

Il s'avère que le client avait tout son code C dans les fichiers .CPP, ce qui était la confusion de leur compilateur dans la production de noms mutilés au lieu de bibliothèques C pur. – Peter

+0

Ouais, les fichiers .cpp produiront des noms mutilés C++ par défaut. S'ils veulent conserver les fichiers .cpp tout en gardant leur API C compatible, ils ont juste besoin d'envelopper leurs fonctions avec 'extern" C "' (dans '#ifdef __cplusplus' comme le dernier extrait de http://stackoverflow.com/a/67985/632035). –