Android NDK開発でよくあるエラー

5268 ワード

エラー1:
make: *** No rule to make target `/cygdrive/d/1-workspace/showmap-android-opengles/jni/showmap_opengles_OpenGLESRenderer.c', needed by `/cygdrive/d/1-workspace/showmap-android-opengles/obj/local/armeabi/objs/OpenGLESMap/showmap_opengles_OpenGLESRenderer.o'.  Stop.
このエラーはshowmap_opengles_OpenGLESRenderer.c showmapに変更_opengles_OpenGLESRenderer.cppの後に現れます.もちろんandroidです.mkファイルにも対応する変更があります
objフォルダを削除します.キャッシュ情報があるとshowmap_を探すことになります.opengles_OpenGLESRenderer.c見つからなかった.
エラー2:
JNI:no implementation found in native...(転載http://laokaddk.blog.51cto.com/368606/1349386)
Javahによる問題
BUG: D/dalvikvm( 1704): Trying to load lib/data/data/com.ulang/lib/libulangaudio.so 0x41052a38 D/dalvikvm( 1704): Shared lib '/data/data/com.ulang/lib/libulangaudio.so' already loaded in same CL 0x41052a38 W/dalvikvm( 1704): No implementation found for native Lcom/ulang/AudioLib;. sayHelloEx ()Ljava/lang/String; D/AndroidRuntime( 1704): Shutting down VM W/dalvikvm( 1704): threadid=1: thread exiting with uncaught exception (group=0x409961f8) E/AndroidRuntime( 1704): FATAL EXCEPTION: main E/AndroidRuntime( 1704): java.lang.UnsatisfiedLinkError: sayHelloEx E/AndroidRuntime( 1704):       at com.ulang.AudioLib.sayHelloEx(Native Method) E/AndroidRuntime( 1704):       at com.ulang.One.onClick(One.java:76) E/AndroidRuntime( 1704):       at android.view.View.performClick(View.java:3480) E/AndroidRuntime( 1704):       at android.view.View$PerformClick.run(View.java:13983) E/AndroidRuntime( 1704):       at android.os.Handler.handleCallback(Handler.java:605) E/AndroidRuntime( 1704):       at android.os.Handler.dispatchMessage(Handler.java:92) E/AndroidRuntime( 1704):       at android.os.Looper.loop(Looper.java:137)は、2番目のパラメータjavahがjclassとして生成することを発見したため、エラーが発生し、jobjectに置き換えることができる.Javahはすべての状況が2番目の項目をjclassに生成するわけではなく、時には生成されたjobjectでもある.NE:特に注意!define __cplusplus #ifdef __cplusplus extern "C"{ #endif/* * Class:     com_ulang_AudioLib * Method:    sayHelloEx * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_ulang_AudioLib_sayHelloEx  (JNIEnv *, jclass); #ifdef __cplusplus } #endif#endif

実験JNIインタフェースの呼び出しで、成功したり、実行したりすると異常になり、logcatにヒントがあります.
  no implementation found in native ....
後でネットを検索してみると、このような状況がいくつかある可能性があることがわかりました.
  1.関数の名前を書き間違えました
  2.インタフェース関数を変更した場合、プロジェクトを再cleanしてからrebuild allすることを確認します.
以上の2点を確認した後、JNIインタフェースで呼び出されたno implementation errorは現れませんでした.
(2)c++生成を実行する.soライブラリ、次のエラーが発生した場合:(関数も見つかりません)
No implementation found for native Lcom/dgut/android/MainActivity;.stringFromJNI ()Ljava/lang/String;
java.lang.UnsatisfiedLinkError: stringFromJNI
at com.dgut.android.MainActivity.stringFromJNI(Native Method)
解決方法:
Javaに呼び出されるc++関数の前にextern「C」修飾を追加します.例えば:(NDK exampleのcppファイルもこのように宣言されています.hello-gl 2を参照)
extern "C" {
	JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz );
}

JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz )
{
    return env->NewStringUTF("Hello from JNI bear c++");
}

理由は次のとおりです.
extern「C」で修飾された変数と関数はC言語でコンパイルされ接続されている.
まず、C++でCのような関数がどのようにコンパイルされているかを見てみましょう.オブジェクト向けの言語として、C++は関数の再ロードをサポートし、プロセス言語Cはサポートしません.関数がC++によってコンパイルされたシンボルライブラリの名前はC言語とは異なる.例えば、ある関数のプロトタイプをvoid foo(int x,int y);この関数はCコンパイラによってコンパイルされたシンボルライブラリの名前は_foo、C++コンパイラは像_を生成しますfoo_int_intなどの名前(コンパイラによって生成される可能性のある名前は異なるが、同じメカニズムを採用しており、生成される新しい名前を「mangled name」と呼ぶ).foo_int_intという名前には,関数名,関数パラメータ数,タイプ情報が含まれており,C++はこのようなメカニズムによって関数リロードを実現している.例えば、C++では、関数voidfoo(int x,int y)とvoid foo(int x,float y)のコンパイルによって生成される符号は異なり、後者は_foo_int_float.同様に、C++の変数は、ローカル変数に加えてクラスメンバー変数およびグローバル変数もサポートされる.ユーザが作成したプログラムのクラスメンバー変数は、グローバル変数と同名である可能性があります.を選択します.本質的には、コンパイラはコンパイルを行う際に、関数の処理と同様に、クラス内の変数にユニークな名前を付け、この名前はユーザープログラムで同名のグローバル変数の名前とは異なる.
したがって、extern「C」修飾関数を使用せずにC言語でコンパイルおよび接続している場合、Jni呼び出しでは関数が見つからない可能性があります.
エラー3:
【回転】JNI呼び出しエラー:No implementation found for native
 
JNI呼び出し時、ずっとNo implementation found for nativeを報告する
 
C++のコードが呼び出された場合、extern「C」を追加する必要があります.
 
【回転】jni呼び出しcとc++の違い.
 
1、JNIEnv*envパラメータの使用
すべてのJNIインタフェースの最初のパラメータはJNIEnv*envです.Cでは、使用方法は
(*env)->NewStringUTF(env, "Hello from JNI!");
ただし、C++では、その呼び出し方法は
env->NewStringUTF("Hello from JNI!");
どうしてこんな違いがあるの?hではJNIEnvの定義について知ることができます.
#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
#else
typedef const struct JNINativeInterface* JNIEnv;
#endif
CとC++では定義が異なり,主にCがクラスをサポートしていないため,融通性のある方法が採用されていることがわかる.
 
2、インタフェースが見つからない
JavaでJNIインタフェースを呼び出すと、例外が発生し、ログを見て、次のエラーが発生しました.
WARN/dalvikvm(422): No implementation found for native Lcom/whty/wcity/HelixPlayer;.setDllPath (Ljava/lang/String;)V
何度もコードをチェックして、確かにCppでこのインタフェースが定義されていて、Javaのパッケージ名、クラス名をよく照合していて、確かに間違いはありませんが、なぜこのような問題が発生したのでしょうか.あとでふと思いましたが、JNIインタフェースはCで定義されていますが、今はC++で実現されています.関数定義の前にextern「C」を付ける必要がありますか?このために、CPPファイルのヘッダファイルを定義します.ヘッダファイルには、次のコードセグメントが追加されます.
#ifdef __cplusplus
extern "C"{
#endif
#endif
...
#ifdef __cplusplus
}
もう一度試して、呼び出しに成功しました!