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