Android NDK / JNI: création d'une bibliothèque partagée dépendant d'autres bibliothèques partagées
Je suis en train d'écrire une application android qui veut faire de la JNI appels en une bibliothèque partagée construit en utilisant le NDK. Le truc, c'est cette bibliothèque partagée appels de fonctions fournies par d'AUTRES bibliothèques partagées. Les autres bibliothèques partagées sont C les bibliothèques qui ont été compilés ailleurs.
Voici ce que j'ai essayé:
Mon Environnement:
Je travaille dans Eclipse. J'ai ajouté la prise en charge native et ont un jni de la bibliothèque. Dans cette bibliothèque, j'ai mon code et un répertoire \lib où j'ai copié mes autres .donc les fichiers.
Tentative #1 Android.mk: il suffit de dire à un endroit où les libs sont
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := native_lib
LOCAL_SRC_FILES := native_lib.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog
LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib1
LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib2
include $(BUILD_SHARED_LIBRARY)
Ce construit très bien, mais lorsque j'essaie de le lancer, j'obtiens une erreur indiquant que dlopen(libnative_lib) a échoué parce qu'elle ne pouvait pas charger libsupport_lib1.
Venant ici, j'ai trouvé ceci:
Peut-bibliothèque partagée à l'appel d'une autre bibliothèque partagée?
qui a dit qu'il fallait que j'appel du chargement de la bibliothèque sur toutes les bibliothèques nécessaires. Super!
Tentative n ° 2 de l'Ouverture de chaque bibliothèque de première
static {
System.loadLibrary("support_lib1");
System.loadLibrary("support_lib2");
System.loadLibrary("native_lib");
}
Encore une fois, cela renforce un peu fine, mais quand je cours, je reçois un nouveau message d'erreur:
ne pouvait pas charger libsupport_lib1. findLibrary retourné null.
Maintenant que nous obtenons quelque part. Il ne faut pas le chargement des bibliothèques à la cible.
Tentative N ° 3 De La Copie .les fichiers de projet/libs/armeabi
N'a pas fonctionné. Lors de l'Éclipse construit supprimé les fichiers que j'ai abandonné là.
Tentative #4 Création d'un nouveau module pour chaque bibliothèque
Alors j'ai trouvé ceci:
Android NDK: Lien à l'aide d'un pré-compilé en statique de la bibliothèque
C'est à propos des bibliothèques statiques, mais peut-être que je vais avoir un problème similaire. L'essentiel est que j'ai besoin de déclarer un module pour chaque bibliothèque. Donc, mon nouveau Android.mk ressemble à ceci:
LOCAL_PATH := $(call my-dir)
#get support_lib1
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib1
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib1.so
include $(BUILD_SHARED_LIBRARY)
#get support_lib2
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib2
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib2.so
include $(BUILD_SHARED_LIBRARY)
#build native lib
include $(CLEAR_VARS)
LOCAL_MODULE := native_lib
LOCAL_SRC_FILES := native_lib.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog
LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib1
LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib2
include $(BUILD_SHARED_LIBRARY)
Ce construit! Encore mieux, armeabi a le sos maintenant! Même MIEUX je reçois le message suivant lorsque j'essaie de le lancer (en me disant qu'support_lib1 et 2 ont été ouverts par la fonction LoadLibrary:
Essayer de charger lib /data/app-lib/com.exemple.tst/libsupport_lib1.donc
ajoutée partagée lib /data/app-lib/com.exemple.tst/libsupport_lib1.donc
pas de JNI_OnLoad trouve dans /data/app-lib/com.exemple.tst/libsupport_lib1.donc, ignorant l'initialisation
mais alors...
dlopen échec: impossible de localiser le symbole func_that_exists_in_libsupport_lib.donc référencé par libnative_lib.donc
Edit: Tentative de 5: Utilisation PREBUILT_SHARED_LIBRARY
J'ai donc trouvé ceci:
Comment puis-je créer un Lien prédéfini Bibliothèque partagée pour Android NDK projet?
qui semble être exactement ce que je demande. Leur réponse semble être "ne pas utiliser "build_shared_library' mais plutôt 'utilisation PREBUILT_SHARED_LIBRARY
Bon, essayons.
LOCAL_PATH := $(call my-dir)
#get support_lib1
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib1
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib1.so
include $(PREBUILT_SHARED_LIBRARY)
#get support_lib2
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib2
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib2.so
include $(PREBUILT_SHARED_LIBRARY)
#build native lib
include $(CLEAR_VARS)
LOCAL_MODULE := native_lib
LOCAL_SRC_FILES := native_lib.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog
LOCAL_SHARED_LIBRARIES := support_lib1 support_lib2
include $(BUILD_SHARED_LIBRARY)
Construire... ne! La construction se plaint de symboles manquants maintenant.
Edit: Tentative de 6: tout Aplatir
Je suis donc retourné à la prebuilts de la documentation dans le NDK. Il dit:
Chaque prêtes à l'emploi de la bibliothèque doit être déclaré comme un seul module indépendant du système de construction. Voici un exemple trivial où nous supposons que le fichier "libtruc."est situé dans le même répertoire que le Android.mk ci-dessous:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
Avis que, pour déclarer un tel module, vous avez vraiment besoin de ce qui suit:
Donner le module d'un nom (ici "foo-prêts à l'emploi'). Cela ne doit pas nécessairement correspondre au nom de la prédéfinis de la bibliothèque elle-même.
Attribuer à LOCAL_SRC_FILES le chemin d'accès aux prêts à l'emploi de la bibliothèque que vous fournissez. Comme d'habitude, le chemin est relatif à votre LOCAL_PATH.
Inclure PREBUILT_SHARED_LIBRARY, au lieu de BUILD_SHARED_LIBRARY, si vous fournissez un partagées, bibliothèque. Pour la statique, l'utilisation PREBUILT_STATIC_LIBRARY.
Un préconstruit module de ne pas construire quoi que ce soit. Toutefois, une copie de votre prédéfini bibliothèque partagée sera copié dans $PROJET/obj/local, et un autre va être copié et coupées en $PROJET/libs/.
Essayons donc d'aplatissement tout en œuvre pour correspondre à l'exemple trivial. J'ai copié mes bibliothèques de leurs cosy /dossier lib et les mettre dans la jni de la racine. Puis j'ai fait ceci:
LOCAL_PATH := $(call my-dir)
#get support_lib1
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib1
LOCAL_SRC_FILES := support_lib1.so
include $(PREBUILT_SHARED_LIBRARY)
#get support_lib2
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib2
LOCAL_SRC_FILES := support_lib2.so
include $(PREBUILT_SHARED_LIBRARY)
#build native lib
include $(CLEAR_VARS)
LOCAL_MODULE := native_lib
LOCAL_SRC_FILES := native_lib.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog
LOCAL_SHARED_LIBRARIES := support_lib1 support_lib2
include $(BUILD_SHARED_LIBRARY)
et... même message d'erreur. De plus je suis très certainement PAS de voir la bibliothèque de fichiers copiés à $PROJET/obj/local.
sooooo.... maintenant ce qui?
source d'informationauteur djc6535 | 2014-02-21
Vous devez vous connecter pour publier un commentaire.
Votre problème est avec la convention de nommage. NDK Android et insister sur la bibliothèque partagée noms de toujours commencer avec lib. Sinon, les bibliothèques ne sera pas relié correctement, et non pas copié dans le
libs/armeabi
dossier correctement, et il n'est pas installé sur l'appareil (copié à/data/data/package/lib
répertoire correctement.Si vous renommez
support_lib1.so
àlibsupport_1.so
etsupport_lib2.so
àlibsupport_2.so
et de mettre ces deux fichiers dansjni/lib
répertoire, puis votre Tentative #5 va travailler avec des changements mineurs:BTW, je ne pense pas que vous avez besoin de ce
-L$(SYSROOT)/../usr/lib
.PS N'oubliez pas de mettre à jour Java côté, trop:
Ne sais pas si c'est exactement là où vous êtes, mais voici ce que je sais sur ces sortes de choses.
$(call import-add-path)
et$(call import-module)
LOCAL_EXPORT_
famille de variables.Prédéfinis Bibliothèque Partagée Android.mk
C'est en supposant que les prédéfinis libaries vivre dans un dir structure comme ceci
Si vous n'êtes pas la construction de plusieurs ABI, je suppose que vous pouvez laisser que peu
Du Projet Android.mk
Je vous recommande de mettre toutes les bibliothèques partagées dans un dossier. Quand vous dites
$(call import-module,SharedProjectFolderName)
il recherche un dossier contenant unAndroid.mk
le long du chemin de recherche vous lui avez dit (import-add-path
)Par la manière, vous ne devriez probablement pas spécifier
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib
. Il devrait être de trouver le bon libs de NDK par lui-même. En ajoutant plus de liens chemins seront probablement confondre. La bonne façon est d'exporter l'éditeur de liens chemins que les drapeaux de la sous-modules.AUSSI, vous pouvez utiliser
ndk-build V=1
pour obtenir une tonne d'info sur le pourquoi il ne peut pas trouver les chemins, etcL'option-L donne à l'éditeur de liens d'un chemin d'accès au répertoire dans lequel se bibliothèques. L'option-l donne à l'éditeur de liens d'un nom de fichier de bibliothèque de lien. Le fichier de bibliothèque de noms doivent commencer par "lib". Vos bibliothèques devrait être nommé libsupport_lib1.donc, et libsupport_lib2.. Si vous le faites, alors c'est probablement ce que vous devez faire (en remplacement de tentative #1):
L'éditeur de liens préfixe le nom de la bibliothèque que vous spécifiez à l'aide d'-l avec "lib" et le suffixe ".". (Pourquoi ne vous ont -L$(SYSROOT)/../usr/lib?)
Je crois que les tentatives #1 et #2 ont échoué parce que vous n'avez pas de lien de votre bibliothèque dans votre exécutable - ils ne sont pas mentionnés dans une option-l. Par ailleurs, vous pouvez vérifier vous-même. Décompressez le fichier .fichier apk et de regarder dans le répertoire lib et les sous-répertoires. Sont votre .si les fichiers là?
À la recherche à l'erreur:
Pouvez-vous fournir l'intégralité du message? dlopen() les charges et les liens des bibliothèques dans le processus en cours d'exécution.