浪费了半天时间尝试构建两个共享库,例如从{j}文件夹和子文件夹中的来源mod1
和mod2
(Android NDK编译为libmod1.so
和libmod2.so
),然后让mod1从mod2调用函数。关于如何使构建工作的大量答案,但随后运行时动态链接无效,应用程序在启动时崩溃。
决定发布这个问题并立即回答,以便整个过程的Q和A在一起,并希望其他人不会浪费一天再研究它。
答案 0 :(得分:24)
正确的构建过程相对容易,我的问题是使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:= $(致电my-dir)
包括$(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES:= mod2#这使得libmod1.so依赖于libmod2.so
LOCAL_MODULE:= mod1
LOCAL_SRC_FILES:= mod1 / file1.c
LOCAL_SRC_FILES + = mod1 / file2.cpp
...
include $(BUILD_SHARED_LIBRARY)#这实际上构建了libmod1.so
包括$(CLEAR_VARS)
LOCAL_MODULE:= mod2
LOCAL_SRC_FILES:= mod2 / file1.cc
LOCAL_SRC_FILES + = mod2 / file2.cc
...
include $(BUILD_SHARED_LIBRARY)#this build 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,对吧?错误!它在app启动时崩溃了“不满意的链接”。确切的错误消息是:
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来解决这个问题是徒劳的。终于尤里卡!我按如下方式修改了我的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);
...
}
并且事情开始像魅力......
格雷格