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:
- Cómo las notificaciones push de Linphone son compatibles con Android / iOS
- Java runOnUiThread y Thread.sleep
- SipApi no es compatible con algunos dispositivos
- Push to talk con Android
- Iplementing Jain SIP en Android
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.
- ¿Cómo funciona SIP en la red celular?
- Crear cuenta de SIP de Android mediante programación
- Peer-to-peer llamada SIP con Android SIP Stack?
- Mensajería de chat SIP de Android
- Sipdroid - Otra llamada entrante no se muestra mientras se continúa
- Cómo enviar y recibir Voice Stream utilizando RTP
- API SIP de Android: demostraciones admitidas, pero error 'no soportado'
- PJSUA2 sip aplicación android nativa
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.
- Usos-característica que anula los usos-permiso?
- Diseño de materiales Tipografía – Titulares, Títulos, Espaciado, Aspecto de texto