4

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

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

これらの各オプションを使用して、自分のライブラリをロードする前にSystem.LoadLibrary( "zmq")を明示的に呼び出してみましたが、そうではありませんでした。結果に変化はありませんでした。nmを使用すると、少なくともオプション#2の場合、欠落しているシンボル*zmq_msg_init*が実際にlibmy_lib.soに存在することが確認されます。

リンクされているZeroMQシンボルが見つからない理由について何か考えはありますか?

4

1 に答える 1

14

2番目のライブラリをコンパイルして、Android ndkのメインライブラリにリンクする方法を学びました。私があなたの役に立つかどうか見てみましょう。

以下は、2 番目のライブラリを作成する方法です (私の場合、弾丸物理ライブラリと 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)

次に、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)

次に、すべてのライブラリを正しい順序で Java コードに追加します。

System.loadLibrary("bullet");
System.loadLibrary("irrlicht");
System.loadLibrary("gamescript");
于 2012-05-16T09:33:21.627 に答える