根据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明确谈到在项目中使用预构建的共享对象的可能性时,我不认为我在这里做了一些禁止的事情。但问题是:为什么它会崩溃然后如何解决这个问题呢?
感谢您的帮助!
答案 0 :(得分:1)
回答我自己的问题:必须手动为所有必需的共享对象创建NativeActivity类的子类并调用System.loadLibrary()。另一种解决方案是使用dlopen(),但在这种情况下,必须首先找到应用程序的绝对路径,因为dlopen()仅在传递相对共享对象时查找系统文件夹。