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
Android NDK: load_library: cannot locate srand
提问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 static
ones 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
srand
is 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.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
.
我不知道你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 srand
but 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 文件中,因此很容易包含在您的代码中。