我在谷歌 android-ndk 组中问过这个问题,但没有得到任何答案。
我正在尝试通过单击在独立项目中构建通用模块
“是图书馆”是日食。
该项目同时提供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 api 的库,我该怎么办。(不仅仅是代码)
Thanks
我读完之后共享库可以调用另一个共享库吗? https://stackoverflow.com/questions/6041934/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 加 -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),然后加载
即使您已经加载了 libfoo.so,libbar.so 也总是会失败
在你的过程中。
有一点不同。如果我已经在我的进程中加载了 libfoo.so,则 libbar.so 将成功。
所以,最后的答案是:
- 如果您需要 Android 库项目中的任何共享库,请使用 LOCAL_LDFLAGS := -Lxx -lxx 。
- 您必须为每个所需的共享库调用 System.loadLibrary。这也是在一个库中使用另一个共享库的方法。
- /libs/ 中的库路径放置在 /data/data//lib/ 中。