質問

According to docs/PREBUILTS.html it is allowed to use prebuilt shared objects in NDK apps. So I tried to have my NDK app import a function from a second shared object but as soon as I use a second shared object in my APK the whole shebang crashes even before android_main() is entered. LogCat says:

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

To track this down, I have setup the following minimalistic test case:

int addvals(int a, int b) { return a + b; }

The source containing only this function is now compiled into a shared object using these build files:

# 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)

Now I want to call the addvals() function from my main shared object. The code is once again minimalistic:

#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);
}

The build files for the main shared object look like this:

# 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)

The final shared object (libTEST.so) links just fine. The external dependency to addvals() is resolved and both shared objects (libsharedobjecttest.so and libTEST.so) are placed into my final APK. The ARM architecture is also correct.

However, the APK crashes immediately when trying to load libTEST.so. android_main() is not even entered. When I remove the reference to libsharedobjecttest, the crash goes away and the APK runs fine. So does anybody have an idea why this crashes?

Do I have to resolve any external dependencies manually using dlopen() and dlsym()? But this would be lots of work when an external shared object has a lot of symbols that are needed by the main shared object... :/

Of course, I could use a static library instead of a second shared object but I'd prefer to use a shared object. And as docs/PREBUILTS.html explicitly talks about the possibility of working with prebuilt shared objects in projects I don't think that I'm doing something forbidden here. But the question is: why does it crash then and how to solve this?

Thanks for your help!

役に立ちましたか?

解決

To answer my own question: One has to subclass NativeActivity class and call System.loadLibrary() on all required shared objects manually. An alternative solution is to use dlopen() but in that case one has to find out the absolute path to the app first because dlopen() only looks in system folders when passed a relative shared object.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top