Android NDK - 使两个 native 共享库相互调用

浪费了半天时间尝试构建两个共享库,例如mod1mod2(Android NDK 编译成 libmod1.solibmod2.so),来自jni 文件夹和子文件夹,然后让 mod1 从 mod2 调用一个函数。关于如何使构建工作的大量答案,但是运行时动态链接不起作用,应用程序在启动时崩溃。

决定把这个问题贴出来马上回答,让整个过程的Q和A在一起,希望别人不要再浪费一天的时间去研究了。

最佳答案

正确的构建过程相对容易,我的问题是使 libmod1.so 依赖于 libmod2.so 在启动时导致不满意的链接 - mod1 代码找不到 mod2 共享库,即使两者都存在于同一文件夹中最终的 APK,在 libs/armeabi、libs/x86 等下。但是,为了使我的答案完整:

  • 将 C 或 C++ 源代码和头文件放在 Android 项目中 jni 目录的子目录下,例如文件夹 mod1/和 mod2/

  • 根据 NDK 指令,创建 Application.mk 文件,例如我的是:

NDK_TOOLCHAIN_VERSION=4.7
APP_PLATFORM := android-8
APP_ABI := armeabi armeabi-v7a x86

  • 按照此模板创建 Android.mk:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := mod2    # this makes libmod1.so dependent on libmod2.so
LOCAL_MODULE := mod1
LOCAL_SRC_FILES := mod1/file1.c
LOCAL_SRC_FILES += mod1/file2.cpp
...
include $(BUILD_SHARED_LIBRARY)    # this actually builds libmod1.so

include $(CLEAR_VARS)
LOCAL_MODULE := mod2
LOCAL_SRC_FILES := mod2/file1.cc
LOCAL_SRC_FILES += mod2/file2.cc
...
include $(BUILD_SHARED_LIBRARY)    # this builds libmod2.so

就是这样,所有构建都没有提示 ndkbuild 脚本。您只需要一个 C 包装器就可以从 Java 调用一些函数。这是我的问题。因为我只有在 libmod1.so 中有可从 Java 调用的函数,所以我在 Java 中的 C 包装类就像:

public class CWrapper {
    static {
        System.loadLibrary("mod1");
    }
    public static native int func1(String aParam);
    ...
}

这对我来说似乎完全合乎逻辑 - 我从 Java 调用 libmod1.so,所以我使用了 System.loadLibrary("mod1"),并且由于 libmod1.so 知道它依赖于 libmod2.so,并且这两个文件都在同一个文件夹,libmod1 会知道如何查找和加载 libmod2,对吧?错误的!它在应用程序启动时因“不满意的链接”而崩溃。确切的错误信息是:

java.lang.UnsatisfiedLinkError: Cannot load library: soinfo_link_image(linker.cpp:1635): could not load library "libmod2.so" needed by "libmod1.so"; caused by load_library(linker.cpp:745): library "libmod2.so" not found

我到处寻找更多代码以添加到 Android.mk 以解决此问题,但徒劳无功。终于 Eureka 了!我修改了我的 CWrapper 类如下:

public class CWrapper {
    static {
        System.loadLibrary("mod2"); // must be first, as mod1 depends on mod2!
        System.loadLibrary("mod1");
    }
    public static native int func1(String aParam);
    ...
}

事情开始变得像魅力一样......

格雷格

https://stackoverflow.com/questions/17688327/

相关文章:

msbuild - Mercurial/Kiln + MSBuild + MSTest 的持续集成建

android - 如何使用 Expo CLI 为 android 构建 64 位 native 代

android - 在 Gradle 产品 flavor 上调试签名配置

eclipse - noClassDefFoundError 使用 Eclipse 的 Scala

xcode - 学习和理解 Xcode 构建系统

gradle - 启动一个 Gradle 守护进程,1 个忙碌和 6 个停止的守护进程无法重用,使用

android - 运行 Android Studio gradle build 时如何使用所有 C

ios - 使用 iOS 构建主机时 Xamarin 实际在做什么?

c++ - 关于如何部署 C++ 代码以在任何地方工作的提示

build - 递归 CMake 搜索头文件和源文件