2011-06-15 7 views
12

아침!Android NDK 가져 오기 모듈/코드 재사용

저는 JNI를 통해 Java와 C++ 사이의 객체를 동적으로 직렬화 할 수있는 작은 NDK 프로젝트를 만들었습니다. 논리는 다음과 같이 작동

콩 -> JavaCInterface.Java -> JavaCInterface.cpp -> JavaCInterface.java -> 콩

문제는 내가 다른 프로젝트에서이 기능을 사용할 수 있습니다. 필자는 테스트 코드를 프로젝트에서 분리하고 "테스터"프로젝트를 만들었습니다. 테스터 프로젝트는 자바 객체를 C++로 보냅니다. 그런 다음 자바 객체를 다시 자바 레이어로 에코합니다.

: Android.mk에 다음 줄을 포함하여 (좌절의 하루 일반적으로 NDK/JNI의 측면에서 "단순"입니다) 나는 소스 프로젝트로 JNIBridge 프로젝트를 추가 -

나는 꽤 간단 할 것입니다 연결 생각한

NDK_MODULE_PATH=.../JNIBridge/jni/"

JNIBridge/JNI/JavaCInterface/Android.mk :

... 
include $(BUILD_STATIC_LIBRARY) 

JNITester/JNI/Android.mk :

... 
include $(BUILD_SHARED_LIBRARY) 
$(call import-module, JavaCInterface) 

이 모두 정상적으로 작동합니다. JavaCInterface 모듈의 헤더에 의존하는 C++ 파일은 정상적으로 작동합니다. 또한 Java 클래스는 JNIBridge 프로젝트의 인터페이스를 행복하게 사용할 수 있습니다. 모든 연결 고리가 행복합니다.

네이티브 메소드 호출을 포함하는 JavaCInterface.java는 정적 라이브러리에있는 JNI 메소드를 볼 수 없습니다. (논리적으로는 같은 프로젝트에 있지만 두 가지 모두 위의 메커니즘을 통해 프로젝트에 사용하기 위해 가져옵니다.)

현재 해결 방법은 다음과 같습니다.


내 현재의 솔루션과 같이 호출 프로젝트의 JavaCInterface의 CPP 파일을 포함하는 것입니다 :

나는 누군가가 내가 달성하기 위해 노력하고있어의 모듈 특성을 보존 무언가를 제안 할 수 바라고 있어요
LOCAL_SRC_FILES := FunctionTable.cpp $(PATH_TO_SHARED_PROJECT)/JavaCInterface.cpp 

JavaCInterface 아키텍처를 변경하면 각 프로젝트를 업데이트해야하는 경우가 있으므로이 작업을 수행하지 않을 것입니다.


각 로컬 프로젝트에 새 JNI 메소드 서명 세트를 생성 한 다음 가져온 모듈에 연결할 수 있습니다. 다시 말하지만, 이것은 구현을 너무 단단히 묶습니다.

답변

14

많은 피땀과 눈물이 난 후에 이것을 알아 냈습니다.

  • Android JNI는 SHARED_LIBRARY에서만 바이너리를로드합니다.
  • JNI는로드 된 공유 라이브러리의 적절한 메소드 서명/스텁에 원시 호출을 연결하려고 시도합니다 (링크 된 공유 라이브러리 내부는 보이지 않습니다).
  • 이러한 방법으로 정적 라이브러리를 만들고 응용 프로그램에서 사용하는 공유 라이브러리에 빌드 할 수 있습니다.

당신은 당신의 Andriod.xml에 다음 코드를 사용하여 원본 프로젝트에 정적 라이브러리를 구축 할 수 있습니다 :

include $(CLEAR_VARS) 
LOCAL_CFLAGS := -O0 
LOCAL_MODULE := LibraryToBeUsedInsideSharedLib 
LOCAL_SRC_FILES := ... 
include $(BUILD_STATIC_LIBRARY) // This builds a "Static Object" here: 
           // /Project/obj/local/armeabi/libLibraryToBeUsedInsideSharedLib.a 

include $(CLEAR_VARS) 
LOCAL_MODULE  := LibraryCalledFromJava 
LOCAL_SRC_FILES := ... 
LOCAL_STATIC_LIBRARIES := LibraryToBeUsedInsideSharedLib 
include $(BUILD_SHARED_LIBRARY) 

LOCAL_STATIC_LIBRARIES

이 공유 라이브러리에 정적 라이브러리가 포함되어 있습니다. 자바 코드에서 당신은 지금이 호출 할 수 있습니다 :

System.loadLibrary("LibraryCalledFromJava"); 

당신은 당신의 자바 코드의 어느 지점에서 LibraryToBeUsedInsideSharedLib 라이브러리 내부에있는 네이티브 메소드를 호출 할 수 있어야합니다.

당신은 외부 프로젝트의 Android.xml이를 추가하여 libLibraryToBeUsedInsideSharedLib.a 파일을 내보내고 다른 프로젝트에서 사용할 수 있습니다 :

include $(CLEAR_VARS) 
LOCAL_MODULE   := LibraryToBeUsedInsideSharedLib 
LOCAL_LDLIBS   := -llog/ 
LOCAL_SRC_FILES   := $(MY_PREBUILT_LIB_DIR)/libLibraryToBeUsedInsideSharedLib.a 
include $(PREBUILT_STATIC_LIBRARY)