【问题标题】:How to use a library project with both c and java apis on Android如何在 Android 上使用带有 c 和 java api 的库项目
【发布时间】: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


    【解决方案1】:

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

    LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

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

    【讨论】:

      【解决方案2】:

      我一直在努力解决类似的问题。我想用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,但找不到方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-03
        • 2013-05-12
        相关资源
        最近更新 更多