2011-06-15 59 views
12

早上好!Android NDK导入模块/代码重用

我创建了一个小的NDK项目,它允许通过JNI在Java和C++之间动态序列化对象。逻辑是这样的:

豆 - > JavaCInterface.Java - > JavaCInterface.cpp - > JavaCInterface.java - >豆

的问题是我想在其他项目中使用此功能。我从项目中分离出测试代码并创建了一个“测试器”项目。测试器项目将Java对象发送到C++,然后将其回送到Java层。

我以为链接会很简单 - (NDK中/ JNI的术语“简单”通常是无奈的一天)我加了JNIBridge项目作为源项目,包括以下几行Android.mk:

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包括静态库的共享库。在Java代码中,你现在可以调用这个:

System.loadLibrary("LibraryCalledFromJava"); 

你应该能够调用位于LibraryToBeUsedInsideSharedLib库内从在Java代码中任何一点的任何本地方法。

可以通过添加这种对外部工程的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)