2012-05-15 7 views
4

C++ 백엔드로 호출하는 Android 애플리케이션을 빌드하려고합니다. 이 백엔드는 메시징을 위해 ZeroMQ를 사용합니다. ZeroMQ 가이드의 android build page에서 ndk 버전 6의 기본 툴체인을 만들고이를 사용하여 ZeroMQ를 성공적으로 빌드했습니다.Android NDK 링크

그러나 JNI 구현으로 내 .so를 빌드하면 모든 것이 제대로로드되지 않는 것처럼 보입니다. 내가 ("zmq")System.loadLibrary를 호출하는 경우 특히,이 성공적으로 완료,하지만 난 후 * 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뿐 아니라)를 내 안드로이드 프로젝트의 폴더 인 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 기호를 찾을 수없는 이유는 무엇입니까?

+0

확인합니다. 또한 종속성이없는 기본 lib가있는 테스트를 실행하는 것을 고려하십시오. 즉, hello-jni ndk 샘플에서 하나를 가져옵니다. –

+0

zeroMQ를 정적으로 연결하여이 문제를 해결할 수 있었지만 C++ stl은 동적으로 지원합니다. – user1243488

답변

13

방금 ​​두 번째 라이브러리를 컴파일하고이를 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) 

는 다음 (libbullet.so 및 libirrlicht.so, 내 경우에는) 당신의 JNI 폴더로 libxxxx.so을 복사합니다. 그리고 주 라이브러리 .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) 

이제 모든 라이브러리를 자바 코드에 올바른 순서로 추가하십시오. 라이브러리는 zip 파일로 열어 APK에 실제로, 장치 (에뮬레이터에 아마 가장 쉬운)에 설치된이 실제로 추출 얻고 있는지 확인

System.loadLibrary("bullet"); 
System.loadLibrary("irrlicht"); 
System.loadLibrary("gamescript"); 
+0

이것이 더 효과적입니다. 그러나 libzmq.so.1도 디렉토리에 복사되고 (apk에 표시 되더라도) libzmq.so.1 대신 libzmq.so.1을 찾고 있으므로로드하는 것을 여전히 거부합니다. – user1243488

+0

라이브러리 (libgamescript.so) 또는 하위 라이브러리 (libbullet.so)가 타사 라이브러리 (예 : libstlport.so)를 사용하는 경우 다른 라이브러리를로드하기 전에 Java에서 stlport를로드해야합니다. (system.loadLibrary ("stlport");) – codetiger

+0

제게 libgnustl_shared.so이고 System.loadLibrary ("gnustl_shared")를 먼저로드합니다. 그러나 여전히 이전에 성공적으로 라이브러리를 찾지 못했다고 주장합니다. – user1243488