java Android NDK:load_library:找不到 srand

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25475055/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:05:15  来源:igfitidea点击:

Android NDK: load_library: cannot locate srand

javaandroidandroid-ndksipunsatisfiedlinkerror

提问by Managarm

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.

我有一个 android 项目,我使用本机代码来处理 SIP(​​使用 libosip2 和 libeXosip2)。我的本机代码与库的源代码一起编译到一个模块中。

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:

我的 Application.mk 看起来像这样:

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

I did check for uncaught dependencies using ndk-depends, which gives me

我确实使用 ndk-depends 检查了未捕获的依赖项,这给了我

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/").

添加 loadLibrary("gnustl_shared") 没有帮助(这是在“libs/armeabi-v7/”中也找到的唯一提到的库之一)。

My Android.mk:

我的 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 ^^

C/C++ 不是我的毅力,所以如果有人能启发我,我将不胜感激:) 作为替代,我的问题的解决方案也很好^^



Update 1

更新 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.

我将 eXosip/osip 库从我的代码中分离出来,将其编译成一个静态库。我还测试了创建共享库并从 Java 内部手动加载它,但失败并显示相同的错误消息。

Update 2

更新 2

I tried using gnustl_shared, static and also stlport - the error remains.

我尝试使用 gnustl_shared、static 和 stlport - 错误仍然存​​在。

采纳答案by Managarm

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 NDKresolved the issue.

感谢 Chris,我意识到我的错误,即使用了适用于 64 位设备NDK。尽管我无法使用最小示例(它似乎特定于 libosip2 和其他可能的示例)来复制错误,但使用 32 位 NDK解决了该问题。

Thank you everyone who took the time to comment and post suggestions!

感谢所有花时间发表评论和提出建议的人!

回答by Micha?l

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.

对于那些在 NDK r10c 上遇到 srand/atof 问题而绊倒这个线程的人:确保将您的 android 目标设置为 19。然后您的应用程序应该可以在 Android 5 (21) 以及所有较低版本上运行。

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).

如果您将 android 目标设置为 21,那么您的应用程序将只能在 Android 5 上运行。但是,您的应用程序将不再适用于所有较低的 android 版本,因为无法找到许多 stdlib 函数(如 srand/atof)。

Kind regards, Micha?l

亲切的问候,迈克尔?

回答by PedroSw7

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*).

同样的问题也发生在 NDK64 r10b 上的int rand(void)int rand_r(unsigned int*)函数(2014 年 9 月)。要重现,只需编译随 NDK64 r10b 提供的任何示例,然后调用int rand(void)int rand_r(unsigned int*)

On NDK32 r10b these functions are defined in stdlib.h as static __inline__, but not on NDK64 r10b.

在 NDK32 r10b 上,这些函数在 stdlib.h 中定义为static __inline__,但在 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!

使用 NDK32 r10b,正如 Managarm 提到的,解决了这个问题,但对于那些想要为 arm64-v8a 目标编译的人来说,它是一个阻塞点!

Came to the conclusion that NDK64 r10b has a bug on this particular point.

得出的结论是 NDK64 r10b 在这一点上存在错误。

Possible patch: replace the original definitions of the missing functions, in the NDK64 r10b stdlib.h, by the staticones from the NDK32 r10b stdlib.h. Ex: for the srand(), it'd become:

可能的补丁:将 NDK64 r10b stdlib.h 中缺失函数的原始定义替换static为 NDK32 r10b stdlib.h 中的定义。例如:对于srand(),它会变成:

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

回答by Alex Cohn

srandis defined as inlinein

srand被定义为内嵌

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

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.shdoes, 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=1to see all actual commands that run the compiler, and check if some unexpected -Iis used somewhere. Maybe, srandis defined in one of the files in $(LOCAL_PATH)/$(OSIP)/includeor $(LOCAL_PATH)/$(EXOSIP)/include.

我不知道你extarct_stuff.sh做了什么,我认为分离静态库(库)没有任何区别。但是,地方你使用非NDK头(也许你的/usr/include,如果你是在Linux上,你可以运行ndk-build V=1地看到,编译运行的所有实际的命令,并检查是否存在意外的-I是用于什么地方。也许,srand在文件中的一个定义在$(LOCAL_PATH)/$(OSIP)/include$(LOCAL_PATH)/$(EXOSIP)/include

回答by AymericM

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.

在 Android 上,应该使用-DHAVE_LRAND48编译osip2。然后,osip2 将不再使用 srand。这将允许您使用任何目标编译 osip2 和 eXosip2。lrand48 至少从 android-3 开始就存在了。

Here are the flags I use to compile osip2 and eXosip2:

以下是我用来编译 osip2 和 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-areslibrary which is a valuable dependancy for osip2/eXosip2.

旁注:以上内容还针对c-ares库进行编译,这是 osip2/eXosip2 的宝贵依赖项。

sidenote2: The above also compiles against openssl library... also valuable for obvious reasons.

旁注2:以上也针对openssl库进行编译......由于显而易见的原因也很有价值。

You may remove HAVE_CARES_H and HAVE_OPENSSL_SSL_H if you wish.

如果您愿意,您可以删除 HAVE_CARES_H 和 HAVE_OPENSSL_SSL_H。

回答by WindRider

In my case the error was not for srandbut for a different function: __ctype_get_mb_cur_max ndk.

在我的情况下,错误不是针对srand而是针对不同的功能:__ctype_get_mb_cur_max ndk.

Fixed it by setting a specific NDK platform version:

通过设置特定的 NDK 平台版本来修复它:

APP_PLATFORM := android-15

APP_PLATFORM := android-15

回答by Itay Bianco

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

如果您无法将目标更改为 19,或者使用实验 gradle 设置 NDK 目标,您仍然可以使用 boost 代替: Boost.Random

The usage is similar to C++ 11. Example:

用法与C++ 11类似。 示例:

#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.

由于实现主要在 .hpp 文件中,因此很容易包含在您的代码中。