Android NDK: load_library: impossible de localiser srand
J'ai un projet android où j'utilise le code natif pour faire des trucs avec le protocole SIP (à l'aide de libosip2 et libeXosip2). D'origine de mon code est compilé avec la bibliothèque de sources dans un même module.
Le code se compile très bien et la bibliothèque générée a tous les symboles-je m'attendre à avoir, mais quand j'essaye de charger la bibliothèque générée j'obtiens l'erreur suivante:
E/eXosip.loadLibrary(9210): java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1307]: 1941 cannot locate 'srand'...
Ma Demande.mk ressemble à ceci:
APP_STL := gnustl_shared
APP_ABI := armeabi-v7a
APP_CPPFLAGS += -fexceptions
Je n'ai vérifier les dépendances avec le ndk-dépend, ce qui me donne
libeXosip_jni.so
libstdc++.so
liblog.so
libgnustl_shared.so
libm.so
libdl.so
libc.so
L'ajout d'une fonction loadLibrary("gnustl_shared") n'aide pas (qui est le seul de ces bibliothèques également trouvé dans les "libs/armeabi-v7/").
Mon Android.mk:
LOCAL_PATH := $(call my-dir)
$(shell (cd $(LOCAL_PATH); sh extract_stuff.sh; cd $(OLDPWD)))
include $(CLEAR_VARS)
OSIP := libosip2-4.1.0
EXOSIP := libeXosip2-4.1.0
LOCAL_MODULE := eXosip
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(OSIP)/include \
$(LOCAL_PATH)/$(EXOSIP)/include
LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(OSIP)/src/osipparser2/*.c)) \
$(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(OSIP)/src/osip2/*.c)) \
$(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(EXOSIP)/src/*.c))
LOCAL_CFLAGS += -DHAVE_FCNTL_H \
-DHAVE_SYS_TIME_H \
-DHAVE_STRUCT_TIMEVAL \
-DHAVE_SYS_SELECT_H \
-DHAVE_PTHREAD \
-DHAVE_SEMAPHORE_H \
-DENABLE_TRACE \
-DOSIP_MT
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := eXosip_jni
LOCAL_STATIC_LIBRARIES := eXosip
LOCAL_LDLIBS := -llog
LOCAL_C_INCLUDES := BackendData.h \
$(LOCAL_PATH)/$(EXOSIP)/include \
$(LOCAL_PATH)/$(OSIP)/include
LOCAL_SRC_FILES := eXosip.cpp \
eXosipCall.cpp
include $(BUILD_SHARED_LIBRARY)
C/C++ n'est pas ma force, donc si quelqu'un pouvait m'éclairer je lui en serais vraiment reconnaissante 🙂 Comme une alternative, une solution à mon problème serait bien aussi ^^
Mise à jour de 1
Je me suis séparé de la eXosip/osip bibliothèque de mon code, le compiler dans une bibliothèque statique. J'ai aussi testé la création d'une bibliothèque partagée et de les charger à la main à partir de l'intérieur de Java, il échoue avec le même message d'erreur.
Mise à jour 2
J'ai essayé d'utiliser gnustl_shared, statique et aussi stlport - l'erreur reste.
Je ne sais toujours pas ce que c'était, donc je vais laisser cette réponse un peu plus longtemps pour voir si quelqu'un peut venir avec une solution réelle. Maintenant, je l'ai eu de travail déclassement mon NDK de r10 à r9d. Pas sûr de ce qui est différent, il me semble que je suis le seul qui a vécu cela.
Deux questions clés: Quels exacte NDK R10 téléchargement avez-vous utilisé? Ensuite, effectuez l'une des lignes dans la sortie de
find YOUR_NDK_R10_DIRECTORY -name "stdlib.h" | xargs grep "srand("
pas spécifier "en ligne" ?Salut, @Managarm, vous souvenez-vous de la cause de cela? J'ai du mal à comprendre pourquoi cela se produit. Dans mon cas, c'est une autre fonction qui fait partie de la libc. Comment diable est-il absent?
Dans mon cas, c'était parce que j'ai été en utilisant le 64 bits NDK. À l'aide de l'32bit NDK a fonctionné pour moi.
OriginalL'auteur Managarm | 2014-08-24
Vous devez vous connecter pour publier un commentaire.
Pour ceux d'achoppement sur ce fil, tout en ayant de la difficulté avec srand/atof sur NDK r10c: assurez-vous de définir votre android cible à 19. Votre application devrait alors fonctionner sur Android 5 (21) ainsi que toutes les versions inférieures.
Si vous définissez votre android cible à 21, alors que votre application s'exécute UNIQUEMENT sur Android 5.
Votre application sera toutefois plus travailler sur toutes les versions d'android inférieures, parce que beaucoup de stdlib fonctions ne peuvent pas être trouvés (comme srand/atof).
Salutations,
Michaël
OriginalL'auteur
Merci à Chris, j'ai réalisé mon erreur, qui a été à l'aide de la NDK prévu pour 64bit appareils. Bien que je ne pouvais pas reproduire l'erreur à l'aide d'un exemple minimal (il semble être spécifique à libosip2 et probablement d'autres), à l'aide de l'32bit NDK résolu le problème.
Merci à tous ceux qui ont pris le temps de commenter et poster des suggestions!
Cela a fonctionné, mais il probablement pas une voie viable pour l'avenir que cela signifie d'être lié à un daté du NDK libération. Je soupçonne que Michaël la réponse de mentionner le rôle hors de l'android fixation de la cible sera plus utile que le temps passe.
Le problème n'est pas du tout spécifique à libosip2. Une bibliothèque à l'aide de srand échouera avec l'ancien Android cible et non pas avec une version plus récente. Pour utiliser libosip2 avec n'importe quel Android cible, voir ma réponse et l'utilisation de -DHAVE_LRAND48
OriginalL'auteur
Le même problème se pose également pour
int rand(void)
etint rand_r(unsigned int*)
fonctions sur NDK64 r10b (septembre 2014).. À reproduire, juste compiler un des exemples fournis avec le NDK64 r10b, et de faire un appel àint rand(void)
ouint rand_r(unsigned int*)
.Sur NDK32 r10b ces fonctions sont définies dans stdlib.h comme
static __inline__
, mais pas sur NDK64 r10b.À l'aide de NDK32 r10b, comme mentionné par Managarm, résout le problème, mais c'est un point de blocage pour ceux qui veulent compiler pour le arm64-v8a cible!
Est venu à la conclusion que NDK64 r10b a un bug sur ce point particulier.
Patch Possible: remplacer les définitions des fonctions manquantes, dans le NDK64 r10b stdlib.h, par la
static
celles de la NDK32 r10b stdlib.h.Ex: pour la
srand()
, ça deviendrait:OriginalL'auteur
Sur Android, osip2 doit être compilé avec -DHAVE_LRAND48. Ensuite, osip2 de ne pas utiliser plus srand. Cela vous permettra de compiler osip2 et eXosip2 avec n'importe quelle cible. lrand48 existe au moins depuis android 3.
Ici sont les indicateurs que j'utilise pour compiler osip2 et eXosip2:
note: ci-dessus compile également contre c-ares de la bibliothèque qui est un précieux dépendance pour osip2/eXosip2.
sidenote2: ci-dessus compile également contre la bibliothèque openssl... aussi utile, pour des raisons évidentes.
Vous pouvez supprimer HAVE_CARES_H et HAVE_OPENSSL_SSL_H si vous le souhaitez.
OriginalL'auteur
Dans mon cas, l'erreur n'était pas pour
srand
mais pour une fonction différente:__ctype_get_mb_cur_max ndk
.Fixé par la fixation d'un spécifique NDK version de plate-forme:
APP_PLATFORM := android-15
OriginalL'auteur
srand
est défini comme inline dansNDK/platforms/android-19/arch-arm/usr/include/stdlib.h
:Je ne peux pas dire ce que votre
extarct_stuff.sh
fait, et je ne pense pas que la séparation de la bibliothèque statique (bibliothèques) fait une différence. Mais quelque part, vous êtes à l'aide de non-NDK-têtes (peut-être que votre/usr/include
, si vous êtes sur Linux. Vous pouvez exécuterndk-build V=1
pour voir tous les commandes exécuter le compilateur, et vérifier si certains inattendu-I
est utilisé quelque part. Peut-être,srand
est défini dans l'un des fichiers dans$(LOCAL_PATH)/$(OSIP)/include
ou$(LOCAL_PATH)/$(EXOSIP)/include
.OriginalL'auteur
Si vous êtes incapable de changer de cible à 19, ou de l'utilisation expérimentale gradle pour définir le NDK cible, vous pouvez toujours utiliser boost à la place:
Coup de pouce.Aléatoire
L'utilisation est similaire à C++ 11. Exemple:
Depuis la mise en œuvre est principalement en .php les fichiers, il est assez facile de les inclure dans votre code.
OriginalL'auteur