0

根据 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 明确谈到在项目中使用预建共享对象的可能性,我认为我在这里没有做任何禁止的事情。但问题是:为什么它会崩溃以及如何解决这个问题?

谢谢你的帮助!

4

1 回答 1

1

要回答我自己的问题:必须继承 NativeActivity 类并在所有必需的共享对象上手动调用 System.loadLibrary()。另一种解决方案是使用 dlopen() 但在这种情况下,必须首先找出应用程序的绝对路径,因为 dlopen() 仅在传递相对共享对象时才查看系统文件夹。

于 2013-01-03T18:18:04.420 回答