【发布时间】:2012-03-01 03:19:05
【问题描述】:
我在 google android-ndk group 中问过这个问题,但没有得到任何答案。
我正在尝试通过单击在独立项目中构建通用模块 “是图书馆”是日食。 本项目同时提供c api和java api。虽然其中一些 api是相关的。 (这意味着将它们分开不是一个好主意 分为2个项目) 我们将其命名为 common 和 libcommon.so。
当我在另一个项目中使用这个库时(假设 testcommon), 我在项目的 Eclipse 中将公共项目添加为库 资源管理器--> 属性--> Android--> 库--> 添加。 但这只会让我有可能在库中使用 java api。
我还将 libcommon.so 添加为 android.mk 中的 PREBUILT_SHARED_LIBRARY testcommon 项目,以便我可以访问 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 的库,我该怎么办?(不仅仅是代码)
谢谢
阅读Can shared library call another shared library?后,我找到了解决这个问题的方法,但仍然不太确定。
在 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 应用程序,并将 libfoo.so 列为 libbar.so 的依赖项 bar/Android.mk(带有 LOCAL_SHARED_LIBRARIES := foo),然后加载 libbar.so 总是会失败,即使你已经加载了 libfoo.so 在您的过程中。
有一点不同。如果我已经在我的进程中加载了 libfoo.so,那么 libbar.so 将会成功。
所以,最后的答案是:
- 如果您需要 android 库项目中的任何共享库,请使用 LOCAL_LDFLAGS := -Lxx -lxx。
- 您必须为每个需要的共享库调用 System.loadLibrary。这也是在一个库中使用另一个共享库的方法。
- /libs/ 处的库路径放在/data/data//lib/。
【问题讨论】:
标签: android android-ndk android-library