我有一个android项目,我使用本机代码来处理SIP(使用libosip2和libeXosip2)。我的本机代码与库一起编译'来源于一个模块。
代码编译得很好,生成的库包含了我期望它拥有的所有符号,但是当我尝试加载生成的库时,我收到以下错误:
E/eXosip.loadLibrary(9210): java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1307]: 1941 cannot locate 'srand'...
我的Application.mk看起来像这样:
APP_STL := gnustl_shared
APP_ABI := armeabi-v7a
APP_CPPFLAGS += -fexceptions
我确实使用ndk-depends检查了未捕获的依赖项,这给了我
libeXosip_jni.so
libstdc++.so
liblog.so
libgnustl_shared.so
libm.so
libdl.so
libc.so
添加一个loadLibrary(" gnustl_shared")没有帮助(这是在" libs / armeabi-v7 /&#34中找到的唯一一个提到的库;)。
我的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 ++不是我的坚韧,所以如果有人能够启发我,我真的很感激:)作为替代方案,解决我的问题也会很好^^
更新1
我将eXosip / osip库与我的代码分开,将其编译成静态库。我还测试了创建一个共享库并从Java内部手动加载它,它失败并出现相同的错误消息。
更新2
我尝试使用gnustl_shared,static和stlport - 错误仍然存在。
答案 0 :(得分:18)
对于那些在NDK r10c上遇到srand / atof问题而绊倒在这个线程上的人:确保你的android目标设置为19.你的应用程序应该适用于Android 5(21)以及所有较低版本。
如果您将Android目标设置为21,那么您的应用程序将仅在Android 5上运行。 但是你的应用程序将不再适用于所有较低的Android版本,因为无法找到很多stdlib函数(如srand / atof)。
亲切的问候, 迈克尔
答案 1 :(得分:2)
感谢Chris,我意识到我的错误,即使用用于64位设备的 NDK 。虽然我无法使用最小的示例复制错误(它似乎特定于libosip2以及其他可能),但使用32位NDK 解决了这个问题。
感谢所有花时间发表评论并发布建议的人!
答案 2 :(得分:2)
同样的问题也发生在NDK64 r10b上的int rand(void)
和int rand_r(unsigned int*)
函数(2014年9月)。要重现,只需编译随NDK64 r10b提供的任何样本,并拨打电话int rand(void)
或int rand_r(unsigned int*)
。
在NDK32 r10b上,这些函数在stdlib.h中定义为static __inline__
,但不在NDK64 r10b中定义。
如Managarm所述,使用NDK32 r10b解决了这个问题,但对于想要编译arm64-v8a目标的人来说,它是一个阻塞点!
得出的结论是NDK64 r10b在这一点上有一个错误。
可能的补丁:用NDK32 r10b stdlib.h中的static
替换NDK64 r10b stdlib.h中缺失函数的原始定义。
例如:对于srand()
,它会成为:
static __inline__ void srand(unsigned int __s)
{
srand48(__s);
}
答案 3 :(得分:0)
srand
在
NDK/platforms/android-19/arch-arm/usr/include/stdlib.h
:
static __inline__ void srand(unsigned int __s) {
srand48(__s);
}
我不知道你的extarct_stuff.sh
是做什么的,我不认为分离静态库(库)会有所不同。但是在某些地方你使用的是非NDK标头(也许是你的/usr/include
,如果你在Linux上。你可以运行ndk-build V=1
来查看运行编译器的所有实际命令,并检查是否有一些意外的{{1}在-I
或srand
中的某个文件中定义了$(LOCAL_PATH)/$(OSIP)/include
。
答案 4 :(得分:0)
在Android上,应使用 -DHAVE_LRAND48 编译osip2。然后,osip2将不再使用srand。这将允许您使用任何目标编译osip2和eXosip2。 lrand48至少存在于android-3之后。
以下是我用来编译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
旁注:以上也编译了c-ares库,这是osip2 / eXosip2的重要依赖。
sidenote2:以上也针对openssl库进行编译......由于显而易见的原因也很有价值。
如果您愿意,可以删除HAVE_CARES_H和HAVE_OPENSSL_SSL_H。
答案 5 :(得分:0)
就我而言,错误不适用于srand
,而是适用于其他功能:__ctype_get_mb_cur_max ndk
。
通过设置特定的NDK平台版本来修复它:
APP_PLATFORM := android-15
答案 6 :(得分:-1)
如果您无法将目标更改为19,或使用实验性gradle设置NDK目标,您仍然可以使用boost: Boost.Random
用法类似于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);
}
由于实现主要是在.hpp文件中,因此很容易包含在您的代码中。