gre*_*gko 18 java-native-interface android build shared-libraries android-ndk
尝试从jni文件夹和子文件夹中的源代码构建两个共享库,例如mod1和mod2(Android NDK编译到libmod1.so和libmod2.so),然后让mod1从mod2调用一个函数.关于如何使构建工作的大量答案,但随后运行时动态链接无法正常工作,应用程序在启动时崩溃.
决定发布这个问题并立即回答,以便整个过程的Q和A在一起,并希望其他人不会浪费一天再研究它.
gre*_*gko 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)
include $(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 构建libmod2.so
这就是它,所有构建都没有抱怨ndkbuild脚本.您只需要一个C包装器来从Java调用一些函数.这是我的问题.因为我只能在libmod1.so中使用Java调用函数,所以Java中的C包装类就像:
public class CWrapper {
static {
System.loadLibrary("mod1");
}
public static native int func1(String aParam);
...
}
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎是完全符合逻辑的 - 我从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
Run Code Online (Sandbox Code Playgroud)
我到处搜索更多代码添加到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);
...
}
Run Code Online (Sandbox Code Playgroud)
事情开始像魅力一样......
格雷格
| 归档时间: |
|
| 查看次数: |
7983 次 |
| 最近记录: |