Android NDK链接

use*_*488 4 android shared-libraries android-ndk

我正在尝试构建一个调用C++后端的android应用程序.此后端使用ZeroMQ进行消息传递.根据ZeroMQ指南中的android构建页面,我构建了一个ndk版本6的本机工具链,并使用它来(成功)构建ZeroMQ.

但是,当我使用JNI实现构建自己的.so时,我似乎无法正常加载所有内容.具体来说,如果我调用System.LoadLibrary("zmq"),这成功完成,但如果我然后调用*System.LoadLibrary("my_lib")*我总是得到一个UnsatisfiedLinkError抱怨:

Cannot load library reloc_library[1244]:   29 cannot locate zmq_msg_init'...
Run Code Online (Sandbox Code Playgroud)

libmy_lib.so已经以几种不同的方式生成,每种方式都没有成功.在生成它之后,我总是将libmy_lib.so(以及libzmq.so)复制到我的android项目的文件夹:libs/armeabi /.

# Compile all object files - this part was done for all options
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -fpic -c Client_Events.cpp \
Client Wrapper.cpp jni.cpp -I /opt/android-root/include/ -I /my/project/specific/stuff

# Option 1 - Don't link the lib in at all
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared  \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o 

# Option 2 - Link ZeroMQ in statically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared  \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
libzmq.a libstdc++.a -Wl,--whole-archive    

# Option 3 - Explicitly link ZeroMQ in dynamically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared  \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
-L /opt/android-root/lib/ -lzmq
Run Code Online (Sandbox Code Playgroud)

对于这些选项中的每一个,我都尝试在加载我自己的库之前显式调用System.LoadLibrary("zmq")而不是.没有什么改变结果.使用nm确认,至少在选项#2的情况下,缺少的符号*zmq_msg_init*确实存在于libmy_lib.so中.

有关为何无法找到链接的ZeroMQ符号的任何想法?

cod*_*ger 13

我刚学会了如何编译第二个库并将其链接到android ndk中的主库.让我看看我对你有用.

以下是我如何创建我的第二个库(在我的例子中,我构建了子弹物理库和irrlicht渲染引擎作为我游戏的2个独立库).

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := HEADER FILES 
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := SRC FILES

LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -ldl -llog

include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)

然后将您的libxxxx.so(在我的情况下,libbullet.so和libirrlicht.so)复制到您的jni文件夹.并在您的主库.mk文件中添加以下内容.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for bullet)
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := libbullet.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for irrlicht)
LOCAL_MODULE := irrlicht
LOCAL_SRC_FILES := libirrlicht.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := (includes for bullet + includes for irrlicht + includes for main code)
LOCAL_SRC_FILES := main code src files

LOCAL_MODULE := gamescript

LOCAL_ARM_MODE   := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -lOpenSLES -landroid -ldl -llog

LOCAL_SHARED_LIBRARIES := bullet irrlicht

include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)

现在,以正确的顺序将所有库添加到您的Java代码中.

System.loadLibrary("bullet");
System.loadLibrary("irrlicht");
System.loadLibrary("gamescript");
Run Code Online (Sandbox Code Playgroud)