Google android-ndk グループでこの質問をしましたが、回答がありません。
「Is Library」をクリックして、独立したプロジェクトで共通モジュールを構築しようとしています。このプロジェクトは、c API と Java API の両方を提供します。これらの API の一部は関連しています。(これは、それらを 2 つのプロジェクトに分けるのは得策ではないことを意味します) common と libcommon.so という名前にしましょう。
このライブラリを別のプロジェクト (testcommon と仮定) で使用している場合、プロジェクト エクスプローラー -> プロパティ -> Android -> ライブラリ -> 追加で、共通プロジェクトを Eclipse のライブラリーとして追加します。しかし、これはライブラリでJava APIを使用できるようにするだけです。
また、libcommon.so を testcommon プロジェクトの android.mk に PREBUILT_SHARED_LIBRARY として追加して、c API にアクセスできるようにします。( 以下のように )
include $(CLEAR_VARS)
LOCAL_MODULE := common-prebuilt
LOCAL_SRC_FILES := ../../common/libs/$(TARGET_ARCH_ABI)/libcommon.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := testCommon
LOCAL_SRC_FILES := testCommon.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../common/jni/include/
LOCAL_SHARED_LIBRARIES := common-prebuilt
include $(BUILD_SHARED_LIBRARY)
このようにして、ndk-build は成功しますが、実行すると以下のエラーが発生します。
[2012-02-29 15:28:20 - testCommon] Error generating final archive:
Found duplicate file for APK: lib/armeabi/libcommon.so
Origin 1: E:\Code\EclipseWorkspace\testCommon\libs\armeabi\libcommon.so
Origin 2: E:\Code\EclipseWorkspace\Common\libs\armeabi\libcommon.so
ライブラリへの参照とビルド前の共有ライブラリの両方が libcommon.so を testcommon プロジェクトに追加するためだと思います。実際、ライブラリのみを参照するか、ビルド前の共有ライブラリを追加するかをテストしましたが、どちらも libcommon.so を testcommon にコピーしました。
問題は、c と Java の両方の API を含むライブラリが必要な場合はどうすればよいかということです。(コードだけでなく)
ありがとう
読んだ後共有ライブラリは別の共有ライブラリを呼び出すことができますか? 、これを解決する方法を見つけましたが、まだよくわかりません。
PREBUILT_SHARED_LIBRARY の代わりに Android.mk で以下の行を使用すると、ネイティブ パーツが機能し、ライブラリがこの方法でコピーされなくなります。そのため、重複コピーを修正できます。
LOCAL_LDFLAGS := -L$(LOCAL_PATH)/../../Common/libs/$(TARGET_ARCH_ABI)/ -lcommon
これが私の前のテストで機能しなかった理由は、この方法であっても、libtestCommon だけでなく、両方のライブラリを Java にロードする必要があるためです。
System.loadLibrary("common"); // I lost this in my before test
System.loadLibrary("testCommon");
今の私には明らかだと思います。
LOCAL_SHARED_LIBRARIES と -L plus -l の両方が NDK で正常に動作するはずです。
問題は、私が電話するときです
System.loadLibrary("testCommon")
/data/data/$(app path)/lib (System.java::loadLibrary --> Runtime.java::loadLibrary --> DexPathList.java::findLibrary ) で so ファイルを見つけようとしますが、libtestCommon がその依存関係 libCommon.so を見つけるために、/vendor/lib と /system/lib でのみ見つけます。
LD_LIBRARY_PATH=/vendor/lib:/system/lib.
最初に System.loadLibrary("common") を呼び出すと、dlopen はそれをキャッシュ (Linker.c::alloc_info) にロードします。これにより、libtestCommon.soがlibCommon.soをロードするようになり、成功したと思います。したがって、すべてが機能します。
また、ndk-r7 の SYSTEM-ISSUES.html の最後に次の単語があることに気付きました。
- バグにより、1 つのアプリケーション共有ライブラリが別のアプリケーション共有ライブラリに依存することが妨げられています。たとえば、アプリケーション用に libfoo.so と libbar.so の両方をビルドし、libfoo.so を libbar.so の依存関係として bar/Android.mk にリストすると (LOCAL_SHARED_LIBRARIES := foo を使用)、libbar.so をロードするとプロセスですでに libfoo.so をロードしている場合でも、常に失敗します。
少し違いがあります。プロセスですでに libfoo.so をロードしている場合、libbar.so は成功します。
したがって、最終的に答えは次のとおりです。
- Android ライブラリ プロジェクトで共有ライブラリが必要な場合は、 LOCAL_LDFLAGS := -Lxx -lxx を使用します。
- 必要な共有ライブラリごとに System.loadLibrary を呼び出す必要があります。これは、1 つのライブラリで別の共有ライブラリを使用する方法でもあります。
- /libs/ にあるライブラリのパスは、/data/data//lib/ に配置されます。