根据 docs/PREBUILTS.html,允许在 NDK 应用程序中使用预构建的共享对象。所以我试图让我的 NDK 应用程序从第二个共享对象导入一个函数,但是一旦我在我的 APK 中使用第二个共享对象,整个 shebang 甚至在输入 android_main() 之前就崩溃了。LogCat 说:
E/AndroidRuntime( 1931):
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.TEST/android.app.NativeActivity}:
java.lang.IllegalArgumentException: Unable to load native library: /data/data/com.example.TEST/lib/libTEST.so
为了追踪这一点,我设置了以下简约测试用例:
int addvals(int a, int b) { return a + b; }
仅包含此函数的源现在使用以下构建文件编译为共享对象:
# Application.mk
APP_MODULES := sharedobjecttest
APP_ABI := armeabi-v7a armeabi
APP_PLATFORM := android-9
# Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sharedobjecttest
LOCAL_SRC_FILES := addvals.c
include $(BUILD_SHARED_LIBRARY)
现在我想从我的主要共享对象中调用 addvals() 函数。代码再次简约:
#include <stdlib.h>
#include <android/log.h>
#include <android_native_app_glue.h>
// prototype for function imported from libsharedobjecttest.so
int addvals(int a, int b);
void android_main(struct android_app* state) {
app_dummy(); // Make sure glue isn't stripped
__android_log_print(ANDROID_LOG_INFO, "LogTag", "Hello World!\n");
__android_log_print(ANDROID_LOG_INFO, "LogTag", "5+6=%d\n", addvals(5, 6));
exit(0);
}
主共享对象的构建文件如下所示:
# Application.mk
APP_ABI := armeabi-v7a armeabi
APP_PLATFORM := android-9
# Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libsharedobjecttest
LOCAL_SRC_FILES := ../../SharedObjectTest/libs/$(TARGET_ARCH_ABI)/libsharedobjecttest.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := TEST
LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS := -llog -landroid
LOCAL_SHARED_LIBRARIES := sharedobjecttest android_native_app_glue
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
最终的共享对象 (libTEST.so) 链接就好了。addvals() 的外部依赖已解决,两个共享对象(libsharedobjecttest.so 和 libTEST.so)都放入了我的最终 APK。ARM架构也是正确的。
但是,当尝试加载 libTEST.so 时,APK 会立即崩溃。android_main() 甚至没有输入。当我删除对 libsharedobjecttest 的引用时,崩溃消失了,APK 运行良好。那么有人知道为什么会崩溃吗?
我是否必须使用 dlopen() 和 dlsym() 手动解决任何外部依赖项?但是当外部共享对象有很多主要共享对象需要的符号时,这将是很多工作......:/
当然,我可以使用静态库而不是第二个共享对象,但我更喜欢使用共享对象。由于 docs/PREBUILTS.html 明确谈到在项目中使用预建共享对象的可能性,我认为我在这里没有做任何禁止的事情。但问题是:为什么它会崩溃以及如何解决这个问题?
谢谢你的帮助!