Androidプロジェクトでは、ネイティブコードを使用してSIP(libosip2とlibeXosip2を使用)を使用しています。ネイティブコードはライブラリと一緒にコンパイルされます。ソースを1つのモジュールにまとめます。
コードは正常にコンパイルされ、生成されたライブラリには期待するすべてのシンボルが含まれていますが、生成されたライブラリを読み込もうとすると、次のエラーが発生します。
E/eXosip.loadLibrary(9210): Java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1307]: 1941 cannot locate 'srand'...
私のApplication.mkは次のようになります。
APP_STL := gnustl_shared
APP_ABI := armeabi-v7a
APP_CPPFLAGS += -fexceptions
Ndk-dependsを使用して、キャッチされていない依存関係をチェックしました。
libeXosip_jni.so
libstdc++.so
liblog.so
libgnustl_shared.so
libm.so
libdl.so
libc.so
LoadLibrary( "gnustl_shared")を追加しても役に立ちません(これは、 "libs/armeabi-v7 /"にもある前述のライブラリの1つだけです)。
私のAndroid.mk:
LOCAL_PATH := $(call my-dir)
$(Shell (cd $(LOCAL_PATH); sh extract_stuff.sh; cd $(OLDPWD)))
include $(CLEAR_VARS)
OSIP := libosip2-4.1.0
EXOSIP := libeXosip2-4.1.0
LOCAL_MODULE := eXosip
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(OSIP)/include \
$(LOCAL_PATH)/$(EXOSIP)/include
LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(OSIP)/src/osipparser2/*.c)) \
$(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(OSIP)/src/osip2/*.c)) \
$(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(EXOSIP)/src/*.c))
LOCAL_CFLAGS += -DHAVE_FCNTL_H \
-DHAVE_SYS_TIME_H \
-DHAVE_STRUCT_TIMEVAL \
-DHAVE_SYS_SELECT_H \
-DHAVE_PTHREAD \
-DHAVE_SEMAPHORE_H \
-DENABLE_TRACE \
-DOSIP_MT
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := eXosip_jni
LOCAL_STATIC_LIBRARIES := eXosip
LOCAL_LDLIBS := -llog
LOCAL_C_INCLUDES := BackendData.h \
$(LOCAL_PATH)/$(EXOSIP)/include \
$(LOCAL_PATH)/$(OSIP)/include
LOCAL_SRC_FILES := eXosip.cpp \
eXosipCall.cpp
include $(BUILD_SHARED_LIBRARY)
C/C++は私の不屈の精神ではないので、誰かが私を教えてくれたら本当にありがたいです:)代わりに、私の問題の解決策もいいでしょう^^
更新1
EXosip/osipライブラリをコードから分離し、静的ライブラリにコンパイルしました。また、共有ライブラリを作成してJava内から手動でロードすることもテストしましたが、同じエラーメッセージが表示されて失敗します。
アップデート2
Gnustl_shared、static、およびstlportを使用してみました-エラーが残ります。
クリスのおかげで、64ビットデバイス用のNDKを使用していたという私の間違いに気づきました。最小限の例を使用してエラーを再現することはできませんでしたが(libosip2およびおそらく他のものに固有のようです)、2ビットNDKを使用問題を解決しました。
コメントや提案の投稿に時間を割いてくださった皆様、ありがとうございました!
NDKr10cでsrand/atofに問題があるときにこのスレッドに遭遇した場合:Androidターゲットを19に設定してください。アプリはAndroid 5(21)で動作するはずです。同様にすべての下位バージョン。
Androidターゲットを21に設定すると、アプリはAndroid 5でのみ実行されます。ただし、アプリはすべての下位Androidバージョンでは動作しなくなります。多くのstdlib関数が見つからないため(srand/atofなど)。
よろしくお願いします、Michaël
NDK64r10bのint Rand(void)
関数とint Rand_r(unsigned int*)
関数でも同じ問題が発生します(2014年9月)。再現するには、NDK64r10bで提供されているサンプルをコンパイルして呼び出します。 int Rand(void)
またはint Rand_r(unsigned int*)
に。
NDK32 r10bでは、これらの関数はstdlib.hで_static __inline__
_として定義されていますが、NDK64r10bでは定義されていません。
Managarmが述べたように、NDK32 r10bを使用すると問題は解決しますが、arm64-v8aターゲット用にコンパイルしたい人にとってはブロッキングポイントです。
NDK64r10bにはこの特定の点にバグがあるという結論に達しました。
考えられるパッチ:NDK64 r10b stdlib.hで欠落している関数の元の定義を、NDK32 r10bstdlib.hのstatic
のものに置き換えます。例:srand()
の場合、次のようになります。
_static __inline__ void srand(unsigned int __s)
{
srand48(__s);
}
_
私の場合、エラーはsrand
ではなく、別の関数でした:__ctype_get_mb_cur_max ndk
。
特定のNDKプラットフォームバージョンを設定することで修正しました:
APP_PLATFORM := Android-15
Androidでは、osip2は-DHAVE_LRAND48でコンパイルする必要があります。その後、osip2はsrandを使用しなくなります。これにより、osip2とeXosip2を任意のターゲットでコンパイルできます。 lrand48は、少なくともAndroid-3以降に存在します。
Osip2とeXosip2のコンパイルに使用するフラグは次のとおりです。
LOCAL_CFLAGS := -fPIC -DPIC -D_POSIX_SOURCE \
-DHAVE_SEMAPHORE_H -DOSIP___FLAGS \
-DHAVE_PTHREAD \
-DHAVE_PTH_PTHREAD_H \
-DHAVE_SYS_TYPES_H \
-DHAVE_SYS_STAT_H \
-DHAVE_FCNTL_H \
-DHAVE_CTYPE_H \
-DHAVE_SYS_SELECT_H \
-DHAVE_UNISTD_H \
-DHAVE_STRTOL \
-DHAVE_LRAND48 \
-DHAVE_TIME_H \
-DHAVE_SYS_TIME_H \
-DHAVE_STRUCT_TIMEVAL -DEXOSIP___FLAGS \
-DHAVE_NETINET_TCP_H \
-DHAVE_ARPA_INET_H \
-DHAVE_ARPA_NAMESER_H \
-DHAVE_RESOLV_H \
-DHAVE_NETDB_H \
-DHAVE_STRING_H \
-DHAVE_STRINGS_H \
-DSRV_RECORD \
-DHAVE_CARES_H \
-DHAVE_OPENSSL_SSL_H
LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DENABLE_TRACE
補足:上記は、osip2/eXosip2の貴重な依存関係である c-ares ライブラリに対してもコンパイルされます。
sidenote2:上記はopensslライブラリに対してもコンパイルされます...明らかな理由からも価値があります。
必要に応じて、HAVE_CARES_HおよびHAVE_OPENSSL_SSL_Hを削除できます。