问题
I have an android project where I use native code to do stuff with SIP (using libosip2 and libeXosip2). My native code is compiled together with the libraries' sources into one module.
The code compiles just fine and the generated library has all the symbols I expect it to have, but when I try to load the generated library I get the following error:
E/eXosip.loadLibrary(9210): java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1307]: 1941 cannot locate 'srand'...
My Application.mk looks like this:
APP_STL := gnustl_shared
APP_ABI := armeabi-v7a
APP_CPPFLAGS += -fexceptions
I did check for uncaught dependencies using ndk-depends, which gives me
libeXosip_jni.so
libstdc++.so
liblog.so
libgnustl_shared.so
libm.so
libdl.so
libc.so
Adding a loadLibrary("gnustl_shared") does not help (which is the only one of the mentioned libraries also found in "libs/armeabi-v7/").
My 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++ is not my fortitude, so if someone could enlighten me I'd be really grateful :) As an alternative, a solution to my problem would also be nice ^^
Update 1
I separated the eXosip/osip library from my code, compiling it into a static library. I also tested creating a shared library and loading it by hand from inside Java, it fails with the same error message.
Update 2
I tried using gnustl_shared, static and also stlport - the error remains.
回答1:
For those stumbling onto this thread while having trouble with srand/atof on NDK r10c: Make sure you set your android target to 19. Your app should then work on Android 5 (21) as well as all lower versions.
If you set your android target to 21, then your app will ONLY run on Android 5. Your app will however no longer work on all lower android versions, because a lot of stdlib functions cannot be found (like srand/atof).
Kind regards, Michaël
回答2:
Thanks to Chris I realized my mistake, which was using the NDK intended for 64bit devices. Though I could not replicate the error using a minimal example (it seems to be specific to libosip2 and possibly others), using the 32bit NDK resolved the issue.
Thank you everyone who took the time to comment and post suggestions!
回答3:
The same problem happens also for int rand(void)
and int rand_r(unsigned int*)
functions on NDK64 r10b (September 2014).. To reproduce, just compile any of the samples provided with the NDK64 r10b, and make a call to int rand(void)
or int rand_r(unsigned int*)
.
On NDK32 r10b these functions are defined in stdlib.h as static __inline__
, but not on NDK64 r10b.
Using NDK32 r10b, as mentioned by Managarm, solves the problem, but it is a blocking point for those who want to compile for the arm64-v8a target!
Came to the conclusion that NDK64 r10b has a bug on this particular point.
Possible patch: replace the original definitions of the missing functions, in the NDK64 r10b stdlib.h, by the static
ones from the NDK32 r10b stdlib.h.
Ex: for the srand()
, it'd become:
static __inline__ void srand(unsigned int __s)
{
srand48(__s);
}
回答4:
On Android, osip2 should be compiled with -DHAVE_LRAND48. Then, osip2 won't use anymore srand. This will allow you to compile osip2 and eXosip2 with any target. lrand48 exists at least since android-3.
Here are the flags I use to compile osip2 and 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: The above also compiles against c-ares library which is a valuable dependancy for osip2/eXosip2.
sidenote2: The above also compiles against openssl library... also valuable for obvious reasons.
You may remove HAVE_CARES_H and HAVE_OPENSSL_SSL_H if you wish.
回答5:
In my case the error was not for srand
but for a different function: __ctype_get_mb_cur_max ndk
.
Fixed it by setting a specific NDK platform version:
APP_PLATFORM := android-15
回答6:
srand
is defined as inline in
NDK/platforms/android-19/arch-arm/usr/include/stdlib.h
:
static __inline__ void srand(unsigned int __s) {
srand48(__s);
}
I cannot tell what your extarct_stuff.sh
does, and I do not think that separating the static library (libraries) makes any difference. But somewhere you are using non-NDK headers (maybe your /usr/include
, if you are on Linux. You can run ndk-build V=1
to see all actual commands that run the compiler, and check if some unexpected -I
is used somewhere. Maybe, srand
is defined in one of the files in $(LOCAL_PATH)/$(OSIP)/include
or $(LOCAL_PATH)/$(EXOSIP)/include
.
回答7:
If you are unable to change the target to 19, or use the experimental gradle to set the NDK target, you can still use boost instead: Boost.Random
The usage is similar to C++ 11. Example:
#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);
}
Since the implementation is mostly in .hpp files, it is pretty easy to include in your code.
来源:https://stackoverflow.com/questions/25475055/android-ndk-load-library-cannot-locate-srand