我花了半天的时间尝试从jni文件夹和子文件夹中的源代码构建两个共享库,例如mod1
和mod2
( Android NDK将其编译为libmod1.so
和libmod2.so
),然后让mod1调用mod2中的函数。有很多关于如何使构建工作的答案,但随后运行时动态链接不起作用,应用程序在启动时崩溃。
我决定发布这个问题并立即回答它,这样整个过程中的Q和A就可以在一起了,希望其他人不会再浪费一天的时间来研究它。
发布于 2013-07-17 07:22:30
正确的构建过程相对简单,我的问题是使libmod1.so依赖于libmod2.so在启动时导致不满意的链接- mod1代码无法找到mod2共享库,即使两者都存在于最终APK中的同一文件夹中,位于libs/armeabi、libs/x86等下。
NDK_TOOLCHAIN_VERSION=4.7
APP_PLATFORM :=安卓-8
APP_ABI := armeabi armeabi-v7a x86
LOCAL_PATH目录$(调用my- := )
包含$(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
..。
包含$(BUILD_SHARED_LIBRARY) #这实际上构建了libmod1.so包含$(CLEAR_VARS)
LOCAL_MODULE := mod2
LOCAL_SRC_FILES := mod2/file1.cc
LOCAL_SRC_FILES += mod2/file2.cc
..。
包含$(BUILD_SHARED_LIBRARY) #这将构建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
复制相似问题