Android NDK: load_library: no se puede localizar srand

Tengo un proyecto androide donde uso código nativo para hacer cosas con SIP (usando libosip2 y libeXosip2). Mi código nativo se compila junto con las fuentes de las bibliotecas en un módulo.

El código compila muy bien y la biblioteca generada tiene todos los símbolos que espero que tenga, pero cuando intento cargar la biblioteca generada consigo el error siguiente:

E/eXosip.loadLibrary(9210): java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1307]: 1941 cannot locate 'srand'... 

Mi Application.mk tiene este aspecto:

 APP_STL := gnustl_shared APP_ABI := armeabi-v7a APP_CPPFLAGS += -fexceptions 

Comprobé dependencias no detectadas usando ndk-depends, lo que me da

 libeXosip_jni.so libstdc++.so liblog.so libgnustl_shared.so libm.so libdl.so libc.so 

La adición de una loadLibrary ("gnustl_shared") no ayuda (que es la única de las bibliotecas mencionadas que también se encuentra en "libs / armeabi-v7 /").

Mi 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 ++ no es mi fortaleza, así que si alguien me puede iluminar sería muy agradecido 🙂 Como alternativa, una solución a mi problema también sería agradable ^ ^


Actualización 1

Separé la biblioteca eXosip / osip de mi código, compilándola en una biblioteca estática. También probé crear una biblioteca compartida y cargarla manualmente desde dentro de Java, falla con el mismo mensaje de error.

Actualización 2

Intenté usar gnustl_shared, estático y también stlport – el error permanece.

Para aquellos que tropiezan con este hilo mientras tienen problemas con srand / atof en NDK r10c: Asegúrese de establecer su objetivo de Android a 19. Su aplicación debe trabajar en Android 5 (21), así como todas las versiones inferiores.

Si defines tu objetivo de Android como 21, entonces tu aplicación solo se ejecutará en Android 5. Sin embargo, tu aplicación ya no funcionará en todas las versiones de Android inferiores, ya que no se pueden encontrar muchas funciones stdlib (como srand / atof).

Saludos cordiales, Michaël

Gracias a Chris me di cuenta de mi error, que estaba utilizando el NDK destinado a dispositivos de 64 bits . Aunque no pude replicar el error usando un ejemplo mínimo (parece ser específico a libosip2 y posiblemente otros), usar el 32bit NDK resolvió el problema.

Gracias a todos los que se tomaron el tiempo para comentar y publicar sugerencias!

El mismo problema ocurre también para las funciones int rand(void) e int rand_r(unsigned int*) en NDK64 r10b (septiembre de 2014) .. Para reproducir, compile cualquiera de los ejemplos proporcionados con el NDK64 r10b y realice una llamada a int rand(void) o int rand_r(unsigned int*) .

En NDK32 r10b estas funciones se definen en stdlib.h como static __inline__ , pero no en NDK64 r10b.

El uso de NDK32 r10b, como se menciona por Managarm, resuelve el problema, pero es un punto de bloqueo para aquellos que quieren compilar para el objetivo arm64-v8a!

Llegó a la conclusión de que NDK64 r10b tiene un error en este punto en particular.

Parche posible: reemplace las definiciones originales de las funciones que faltan, en el NDK64 r10b stdlib.h, por las static del NDK32 r10b stdlib.h. Ex: para el srand() , se convertiría en:

 static __inline__ void srand(unsigned int __s) { srand48(__s); } 

En Android, osip2 debe ser compilado con -DHAVE_LRAND48 . Entonces, osip2 no usará más srand. Esto le permitirá compilar osip2 y eXosip2 con cualquier destino. Lrand48 existe al menos desde android-3.

Aquí están las banderas que utilizo para compilar osip2 y eXosip2:

 LOCAL_CFLAGS := -fPIC -DPIC -D_POSIX_SOURCE \ -DHAVE_SEMAPHORE_H -DOSIP___FLAGS \ -DHAVE_PTHREAD \ -DHAVE_PTH_PTHREAD_H \ -DHAVE_SYS_TYPES_H \ -DHAVE_SYS_STAT_H \ -DHAVE_FCNTL_H \ -DHAVE_CTYPE_H \ -DHAVE_SYS_SELECT_H \ -DHAVE_UNISTD_H \ -DHAVE_STRTOL \ -DHAVE_LRAND48 \ -DHAVE_TIME_H \ -DHAVE_SYS_TIME_H \ -DHAVE_STRUCT_TIMEVAL -DEXOSIP___FLAGS \ -DHAVE_NETINET_TCP_H \ -DHAVE_ARPA_INET_H \ -DHAVE_ARPA_NAMESER_H \ -DHAVE_RESOLV_H \ -DHAVE_NETDB_H \ -DHAVE_STRING_H \ -DHAVE_STRINGS_H \ -DSRV_RECORD \ -DHAVE_CARES_H \ -DHAVE_OPENSSL_SSL_H LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DENABLE_TRACE 

Sidenote: Lo anterior también se compila contra c-ares biblioteca que es una valiosa dependencia para osip2 / eXosip2.

Sidenote2: Lo anterior también se compila contra openssl biblioteca … también valiosa por razones obvias.

Puede quitar HAVE_CARES_H y HAVE_OPENSSL_SSL_H si lo desea.

En mi caso el error no era para srand sino para una función diferente: __ctype_get_mb_cur_max ndk .

Se ha corregido estableciendo una versión específica de la plataforma NDK:

APP_PLATFORM := android-15

srand se define como inline en

NDK/platforms/android-19/arch-arm/usr/include/stdlib.h :

 static __inline__ void srand(unsigned int __s) { srand48(__s); } 

No puedo decir lo que su extarct_stuff.sh hace, y no creo que separar la biblioteca estática (bibliotecas) hace alguna diferencia. Pero en algún lugar que esté usando encabezados que no sean NDK (tal vez su /usr/include , si está en Linux. Puede ejecutar ndk-build V=1 para ver todos los comandos reales que ejecutan el compilador y comprobar si algún inesperado Tal vez, srand se define en uno de los archivos en $(LOCAL_PATH)/$(OSIP)/include o $(LOCAL_PATH)/$(EXOSIP)/include .

Si no puede cambiar el objetivo a 19, o utilizar el gradle experimental para establecer el destino NDK, todavía puede utilizar el impulso en su lugar: Boost.Random

El uso es similar a C ++ 11. Ejemplo:

 #include <boost/random/mersenne_twister.hpp> #include "boost/random.hpp" int main() { boost::mt19937 randomGenerator.seed((unsigned int)time(0)); boost::uniform_int<> uniform(1, 10); return uniform(_randomGenerator); } 

Dado que la implementación es principalmente en archivos .hpp, es bastante fácil de incluir en su código.

  • Cómo implementar la aplicación VOIP utilizando el paquete android.net.rtp
  • ¿Por qué la pila SIP nativa incluida en Android 2.3 no funciona sobre 3g?
  • Chat y aplicación VOIP
  • Aplicación Voz de voz de Android (SIP)
  • Android como puerta de enlace SIP a GSM
  • Android sip pila con el apoyo de manipulación de códec?
  • Personalización de Sipdroid
  • Soporte de api de Sip Manager
  • Error en el registro de Android SIP (-9 IN_PROGRESS)
  • Aplicación VOIP para Android sin acceso a Internet
  • No se puede abrir el dispositivo de sonido: funcionamiento del dispositivo de audio no válido o no admitido
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.