Android NDK: load_library: cannot locate srand

落爺英雄遲暮 提交于 2019-12-17 18:40:25

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!