浪费了半天时间尝试构建两个共享库,例如mod1
和 mod2
(Android NDK 编译成 libmod1.so
和 libmod2.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
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
gradle - 启动一个 Gradle 守护进程,1 个忙碌和 6 个停止的守护进程无法重用,使用
android - 运行 Android Studio gradle build 时如何使用所有 C
ios - 使用 iOS 构建主机时 Xamarin 实际在做什么?