12

早晨!

我创建了一个小型 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 方法签名,然后链接到导入的模块。同样,这将实现绑定得太紧。

4

1 回答 1

16

经过大量的汗水和泪水,我明白了这一点。

  • Android JNI 仅从 a 加载其二进制文件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 代码中的任何位置调用位于库中的任何本机方法。

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)
于 2011-06-16T09:41:29.347 回答