Android NDK связывание

Я пытаюсь создать приложение для Android, которое обращается к бэкэнду C ++. Этот бэкэнд использует ZeroMQ для обмена сообщениями. За страница сборки Andro в руководстве по ZeroMQ я создал собственный набор инструментов ndk версии 6 и использовал его для (успешного) построения ZeroMQ.

Однако когда я создаю свой собственный .so с реализациями JNI, я не могу заставить все загружаться правильно. В частности, если я позвоню System.loadLibrary ( "zmq"), это успешно завершается, но если я затем вызываю * System.LoadLibrary ("my_lib") *, я всегда получаю UnsatisfiedLinkError, жалуясь на то, что:

Cannot load library reloc_library[1244]:   29 cannot locate zmq_msg_init'...

The 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, которые связаны между собой?

 Chris Stratton15 мая 2012 г., 06:37
Проверьте, что ваша библиотека на самом деле находится в apk, открыв ее в виде zip-файла, и убедитесь, что она на самом деле извлекается при установке на устройство (вероятно, проще всего на эмуляторе). Также подумайте о том, чтобы запустить тест, в котором у вас есть собственная библиотека без зависимостей - то есть, взять ее из примера hello-jni ndk.
 user124348822 мая 2012 г., 20:06
Я смог исправить это, статически связав zeroMQ, но c ++ stl поддерживает динамически.

Ответы на вопрос(1)

как скомпилировать вторую библиотеку и связать ее с моей основной библиотекой в Android ndk. Дайте мне посмотреть, буду ли я вам полезен.

Далее я создаю свою вторую библиотеку (в моем случае я строю библиотеку физики маркеров и механизм рендеринга irrlicht как две отдельные библиотеки для своей игры

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");
 codetiger24 мая 2012 г., 09:29
Ответ работает для меня во всех случаях. Я сомневаюсь, что вы следуете тому же порядку. Также еще одно сомнение, вы строите его для многих архитектур?
 FooF04 июн. 2012 г., 08:23
Просто обратите внимание: документ Android NDK включен${NDK}/doc/PREBUILTS.html описывает детали.
 user124348822 мая 2012 г., 19:15
Для меня это libgnustl_shared.so, и я сначала успешно загружаю System.loadLibrary ("gnustl_shared"). Тем не менее, он по-прежнему утверждает, что не может найти библиотеки, которые я ранее успешно загрузи
 codetiger22 мая 2012 г., 07:05
Если ваша библиотека (libgamescript.so) или ваша вспомогательная библиотека (libbullet.so) использует стороннюю библиотеку (как в моем случае, libstlport.so), вам необходимо загрузить stlport из Java перед загрузкой других библиотек. (сначала сделайте system.loadLibrary ("stlport");)
 user124348822 мая 2012 г., 06:56
Это сработало лучше. Тем не менее, он по-прежнему отказывается загружаться, на этот раз потому, что ищет libzmq.so.1, а не libzmq.so, даже если libzmq.so.1 также скопирован в каталог (и отображается в apk).

Ваш ответ на вопрос