0

docs / PREBUILTS.htmlによると、NDKアプリでビルド済みの共有オブジェクトを使用できます。そこで、NDKアプリに2番目の共有オブジェクトから関数をインポートさせようとしましたが、APKで2番目の共有オブジェクトを使用するとすぐに、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()を使用して、外部の依存関係を手動で解決する必要がありますか?ただし、外部共有オブジェクトにメイン共有オブジェクトに必要なシンボルが多数ある場合、これは多くの作業になります...:/

もちろん、2番目の共有オブジェクトの代わりに静的ライブラリを使用することもできますが、共有オブジェクトを使用したいと思います。また、docs / PREBUILTS.htmlが、プロジェクトでビルド済みの共有オブジェクトを操作する可能性について明示的に説明しているので、ここで禁止されていることをしているとは思いません。しかし、問題は、なぜそれがクラッシュするのか、そしてこれをどのように解決するのかということです。

ご協力いただきありがとうございます!

4

1 に答える 1

1

私自身の質問に答えるには、NativeActivityクラスをサブクラス化し、必要なすべての共有オブジェクトに対してSystem.loadLibrary()を手動で呼び出す必要があります。別の解決策はdlopen()を使用することですが、その場合、dlopen()は相対共有オブジェクトを渡されたときにのみシステムフォルダーを検索するため、最初にアプリへの絶対パスを見つける必要があります。

于 2013-01-03T18:18:04.420 に答える