Android NDK:load_library:找不到srand

时间:2014-08-24 18:39:47

标签: java android android-ndk sip unsatisfiedlinkerror

我有一个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 - 错误仍然存​​在。

7 个答案:

答案 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}在-Isrand中的某个文件中定义了$(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文件中,因此很容易包含在您的代码中。