Android NDK note

4502 ワード

JNIEnv *evn   JNI      JNIEnv*     ,    CPP           evn,                。env           , VC      "->"          
jobject obj:jobject      Java         Java    LocalFunction     ,   this
Java , String 。 , Java , C/C++ Unicode。 :

(1)const char*GetStringUTFchars(jstring string,jboolean*isCopy)は、文字列UTF符号化を指すポインタを返し、この文字配列を作成できない場合はnullを返す.このポインタは、ReleaseStringUTFchar()関数を呼び出すまで有効です.パラメータ:string Java文字列オブジェクトisCopyコピーすると、JNI_TRUEが埋め込んだjboolean、そうでなければJNI_を指すFALSEで埋め込まれたjboolean.
 (2)   void ReleaseStringUTFChars(jstring str, const char* chars)
仮想マシンのローカルコードがcharsを介してJava文字列にアクセスする必要がなくなったことを通知します.パラメータ:string Java文字列オブジェクトchars GetStringCharsから返されるポインタ
 (3)   jstring NewStringUTF(const char *utf)
新しいJava文字列を返しutfコンテンツを新しい列にコピーし、文字列オブジェクトを作成できない場合はnullを返します.通常、逆値タイプがstringタイプの場合に使用されます.パラメータ:utf UTF符号化文字列ポインタは、数値型パラメータに対してC/C++で直接使用でき、そのバイト幅は以下の通りである.
 
xxx*GetXxxArrayElements(xxxArray array,jboolean*isCopy)は、Java配列要素を指すCポインタを生成します.不要になった場合は、このポインタをReleaseXxxArrayElementsパラメータに渡す必要があります.array配列オブジェクトisCopyがコピーされた場合は、JNI_を指します.TRUEが埋め込んだjboolean、そうでなければJNI_を指すFALSEで埋め込まれたjboolean.例:jboolean*GetBooleanArrayElements(jbooleanArray array,jboolean*isCopy)
 (4)   void ReleaseXxxArrayElements(xxxArray array,xxx *elems, jint mode)
仮想マシンにGetXxxArrayElementsから取得したポインタが不要になったことを通知します.パラメータ:array配列オブジェクトelemsが不要になった配列要素へのポインタmode 0=配列要素を更新した後にelemsバッファJNIを解放するCOMMIT=配列要素の更新後にelemsバッファJNIを解放しないABORT=配列要素を更新せずにelemsバッファを解放する例:void ReleaseBooleanArrayElements(jbooleanArray array,jboolean*elems,jint mode)
 (5)   xxxArray NewXxxArray(jsize len)
通常、逆値タイプが配列型の場合に使用される新しい配列を生成します.パラメータ:len配列の要素の数.例:jbooleanArray NewBooleanArray(jsize len)
コンパイル共有ライブラリの生成
GCCを使用する場合は、コンパイラがJavaローカルメソッドのサポートファイルをどこで検索するかを通知し、コンパイラが場所に関係のないコードを生成することを明示的に通知する必要があります.私の環境では、gcc-I/home/jbuilder/jdk 1のようにコンパイルされます.3.1/include-I/home/jbuilder/jdk1.3.1/include/linux -fPIC -c Hello.cハローを生成する.o gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 Hello.o libhelloを生成する.so.1.0次に生成された共有ライブラリを標準ファイル名cp libhelloにコピーする.so.1.0 libhello.so
最後に、この共有ファイルのパスをダイナミックリンクプログラムに通知します. export LD_LIBRARY_PATH=`pwd` :$LD_LIBRARY_PATH
  
適用上の注意事項
1.TCP/IPによってJavaコードとローカルC/C++コードとの相互作用を実現できる場合、上述したJNIの方式は使用しないほうがよい.一度のJNI呼び出しは非常に時間がかかり、0.5~1ミリ秒かかるからである.2.1つのAppletアプリケーションでは、JNIは使用しないでください.Appletでセキュリティ異常が発生する可能性があるためです.3.すべてのローカルメソッドを単一クラスにカプセル化し、このクラスは単一DLLを呼び出す.このDLLは、各ターゲット・オペレーティング・システムについて、適切なプラットフォーム固有のバージョンで置き換えることができます.これにより、ローカルコードの影響を最小限に抑えることができ、今後必要な移植問題を含めるのに役立ちます.4.ローカルメソッドは簡単です.生成されたDLLのサードパーティ実行時のDLL依存度を最小限に抑える.ローカルメソッドをできるだけ独立させて、DLLとアプリケーションのロードに必要なオーバーヘッドを最小限に抑えます.ランタイムDLLが必要な場合は、アプリケーションとともに提供する必要があります.5.ローカルコードの実行時に、配列境界エラー、エラーポインタ参照による間接エラーなどを効果的に防ぐことはできません.Java仮想マシンがクラッシュする可能性があるため、ローカルコードの安定性を保証する必要があります.
JNI呼び出し仕様は、既存の他の言語のコードを多重化するために簡単で使いやすいインタフェースを提供し、多くの財力を節約することができ、Javaによる開発速度を楽しむと同時に、古いリソースを放棄する必要がありません.
通常、Androidアプリケーションを開発する際には、OpenGL、OpenCoreのようなマルチメディアアプリケーションのような性能の問題でNDKを使用して実現する必要がある場合があります.ローカルC/C++言語を使用すると、性能に敏感なアルゴリズムや複雑なアルゴリズムを処理することができます.Android 123は、私たちの日常のNDK開発で遭遇した問題やテクニックをまとめ、ネットユーザーが閲覧しやすいようにしています.
     1. Android NDKでコンパイルされたアプリケーションはAndroid 1.5以上のオペレーティングシステムで実行でき、Androidプラットフォームでのローカルコールは主にJNI方式で処理され、JNIコールのオーバーヘッドは小さくなく、簡単な操作であれば蛇足を加える必要はありません.
     2. 一般的にNDKで生成されたsoファイルはどのようにapkにパッケージ化されますか?一般的なエンジニアリングディレクトリの下にlibsフォルダを作成します.もちろん、手動で解放することもできます.例えばdata/data/cnです.com.android123.cwj/files/rmvb-decoder.so
     3. JNIの下で、私たちがよく使う名前は次のとおりです.
    static JavaVM *g_VM;//グローバル環境ポインタ
    static jclass jNativesClass;
  (*env)->GetJavaVM(env, &g_VM);//env環境ポインタを取得し、後でg_VMでいいです.
     4.jobjectArray jargv//java配列
int getArrayLen(JNIEnv*env,jobjectArray jarray):Java配列の長さを取得し、jsizeタイプに戻る
jstring jele = (jstring)(*env)->GetObjectArrayElement(env, jargv, n);//Java配列要素nをローカルのjstringconst char*word=(*env)->GetStringUTFchars(env,jee,0);//Javaのutf文字をcの下のchar*に変換
   5.メモリを解放することを覚えておいてください.これはjavaではありません.
  (*env)->ReleaseStringUTFChars(env, jele, word); 
   6. Javaクラスのネーミング方法について
(Ljava/lang/String;I)Vその中の本文
 I = IntegerB = ByteS = ShortC = CharLXXX; = Lにクラス名を付ける