【问题标题】:Android NDK import-module / code reuseAndroid NDK 导入模块/代码复用
【发布时间】:2011-06-15 08:35:47
【问题描述】:

早上好!

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

Bean -> JavaCInterface.Java -> JavaCInterface.cpp -> JavaCInterface.java -> Bean

问题是我想在其他项目中使用此功能。我从项目中分离出测试代码并创建了一个“Tester”项目。测试器项目将一个 Java 对象发送到 C++,然后 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 方法签名,然后链接到导入的模块。同样,这将实现绑定得太紧。

【问题讨论】:

    标签: java-native-interface android-ndk import-module


    【解决方案1】:

    经过大量的汗水和泪水,我想通了。

    • 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");
    

    您应该能够从您的 java 代码中的任何位置调用位于 LibraryToBeUsedInsideSharedLib 库中的任何本机方法。

    您可以将libLibraryToBeUsedInsideSharedLib.a 文件导出并在其他项目中使用,方法是将其添加到外部项目的Android.xml 中:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-27
      • 2017-11-07
      • 2012-05-17
      • 1970-01-01
      • 2015-12-30
      • 1970-01-01
      • 2019-01-08
      相关资源
      最近更新 更多