2

我在 google android-ndk group 中问过这个问题,但没有得到任何答案。

我正在尝试通过单击“Is Library”在独立项目中构建一个通用模块是 Eclipse。本项目同时提供c api和java api。虽然其中一些 API 是相关的。(这意味着将它们分成 2 个项目并不是一个好主意)让我们将其命名为 common 和 libcommon.so。

当我在另一个项目中使用这个库时(假设 testcommon),我在项目资源管理器中将公共项目添加为 Eclipse 中的库 - > 属性 - > Android - > 库 - > 添加。但这只会让我有可能在库中使用 java api。

我还在 testcommon 项目的 android.mk 中添加 libcommon.so 作为 PREBUILT_SHARED_LIBRARY,以便我可以访问 c api。( 如下 )

include $(CLEAR_VARS) 
LOCAL_MODULE := common-prebuilt 
LOCAL_SRC_FILES := ../../common/libs/$(TARGET_ARCH_ABI)/libcommon.so 
include $(PREBUILT_SHARED_LIBRARY) 

include $(CLEAR_VARS)
LOCAL_MODULE    := testCommon 
LOCAL_SRC_FILES := testCommon.c 
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../common/jni/include/ 
LOCAL_SHARED_LIBRARIES := common-prebuilt 
include $(BUILD_SHARED_LIBRARY) 

这样,ndk-build 是成功的,但是当我运行它时,出现以下错误:

[2012-02-29 15:28:20 - testCommon] Error generating final archive: 
Found duplicate file for APK: lib/armeabi/libcommon.so 
Origin 1: E:\Code\EclipseWorkspace\testCommon\libs\armeabi\libcommon.so 
Origin 2: E:\Code\EclipseWorkspace\Common\libs\armeabi\libcommon.so 

我认为这是因为对库和预构建共享库的引用都将 libcommon.so 添加到 testcommon 项目中。事实上,我测试过只引用该库或添加预构建共享库,它们都将 libcommon.so 复制到 testcommon。

问题是,如果我需要一个同时具有 c 和 java apis 的库,我该怎么办。(不仅是代码)

谢谢


阅读后共享库可以调用另一个共享库吗?,我找到了解决这个问题的方法,但仍然不太确定。

在 Android.mk 中使用以下行代替 PREBUILT_SHARED_LIBRARY 也可以使本机部分正常工作,并且不会以这种方式复制库。这样可以修复重复的副本。

LOCAL_LDFLAGS := -L$(LOCAL_PATH)/../../Common/libs/$(TARGET_ARCH_ABI)/ -lcommon

这在我之前的测试中无法工作的原因是即使这样,两个库都应该在 java 中加载,而不仅仅是 libtestCommon。

System.loadLibrary("common"); // I lost this in my before test
System.loadLibrary("testCommon");

我想我现在很清楚了。

LOCAL_SHARED_LIBRARIES 和 -L plus -l 都应该在 NDK 中正常工作。

问题是当我打电话时

System.loadLibrary("testCommon")

它会尝试在 /data/data/$(app path)/lib (System.java::loadLibrary --> Runtime.java::loadLibrary --> DexPathList.java::findLibrary )找到so文件,但是当 libtestCommon 尝试要找到它的依赖项 libCommon.so,它只会在 /vendor/lib 和 /system/lib 中找到它,因为

LD_LIBRARY_PATH=/vendor/lib:/system/lib.

如果我首先调用 System.loadLibrary("common"),dlopen 会将其加载到缓存中(Linker.c::alloc_info)。我猜这使得 libtestCommon.so 加载 libCommon.so 成功。所以一切正常。

我还注意到 ndk-r7 中 SYSTEM-ISSUES.html 末尾的这些词:

  • 一个错误会阻止一个应用程序共享库依赖于另一个应用程序共享库。例如,如果您为您的应用程序同时构建 libfoo.so 和 libbar.so,并在 bar/Android.mk 中将 libfoo.so 列为 libbar.so 的依赖项(使用 LOCAL_SHARED_LIBRARIES := foo),那么加载 libbar.so 将总是失败,即使你已经在你的进程中加载​​了 libfoo.so。

有一点不同。如果我已经在我的进程中加载​​了 libfoo.so,那么 libbar.so 将会成功。

所以,最后的答案是:

  • 如果您需要 android 库项目中的任何共享库,请使用 LOCAL_LDFLAGS := -Lxx -lxx。
  • 您必须为所需的每个共享库调用 System.loadLibrary。这也是在一个库中使用另一个共享库的方法。
  • /libs/ 的库路径放在/data/data//lib/。
4

2 回答 2

0

我一直在努力解决类似的问题。我想用Java和C构建一个Android库项目。我希望依赖项目的Java能够在JNI中引用库的Java和依赖项目的C代码,以便能够在库的jni中引用C。我需要两个kludges。一个与您的解决方案几乎相同:

LOCAL_LDFLAGS := -L$(LOCAL_PATH)/../../Common/libs/$(TARGET_ARCH_ABI)/ -lcommon

我创建了对文件系统中库项目实际位置的依赖项。您的依赖项假定Common库项目是您依赖的TestCommon项目的同级目录。

我还创建了一个 build.xml Ant 文件,它将 C 头文件从库项目复制到依赖 jni 文件夹中的 jni/include 目录。

有了这两个kludges,我就能让一切正常工作。我真的很想消除这两个kludges,但找不到办法。

于 2014-03-31T00:28:33.237 回答
0

作为一个选项,您可以使用

LOCAL_ALLOW_UNDEFINED_SYMBOLS := 真

在 Android.mk 之一中并排除重复的库。

于 2013-11-25T15:46:50.813 回答