2011.12.08
【Android NDK】Cから例外を出力する
GLSLのコンパイルが失敗したことに気づかないことが多いので
エラーが出たら例外を出力しプログラムをとめたい。
おおまかな例外の出力方法はここを参照。
Link:JNIコーディングメモ(Hishidama's Java native interface coding Memo)
簡単なExceptionであればenv->ThrowNewを実行すればいいらしい。
しかしこれも日本語が表示できないわけです。
ということでJava側に自分用のクラスを作ってそれをenv->Throwする方法にする。
こんな感じ。
/** * 例外を発生させる */ void throwException( char *szFile, int nLine, char *szInfo ) { JNIEnv *env = getJNIEnv(); jbyteArray jaryStr; char szClassName[256]; char szText[4096]; //クラス名作成 szClassName[0] = '\0'; strcat( szClassName, PROJECT_PACKAGE_NAME ); strcat( szClassName, "/NdkException" ); //例外文字列の作成 sprintf( szText, "file:%s Line:%d\n%s", szFile, nLine, szInfo ); //文字列情報をByteArray化 jaryStr = (*env)->NewByteArray( env, strlen( szText ) ); (*env)->SetByteArrayRegion( env, jaryStr, 0, strlen( szText ), (jbyte*)szText ); //自前のExceptionクラスの作成 コンストラクタ名はクラス名でなく<init>になる jclass clsj = (*env)->FindClass( env, szClassName ); jmethodID cm = (*env)->GetMethodID( env, clsj, "<init>", "([B)V" ); jobject obj = (*env)->NewObject( env, clsj, cm, jaryStr ); //送信 (*env)->Throw( env, obj ); //後処理 (*env)->DeleteLocalRef( env, obj ); (*env)->DeleteLocalRef( env, jaryStr ); (*env)->DeleteLocalRef( env, clsj ); }
要注意のところはコンストラクタの関数名。
クラス名ではなく"<init>"らしい。
JavaだとThrowした瞬間にとまるけど、Cにはそんな機構がないので走り続ける。
なので例外を出しているかはわかるのでjavaに戻るまで即座にreturnし続けて始めて例外として認識される。
このあたりの管理が面倒ですね。
C++でも例外があるのでこれをうまく使ってJava側へ例外投げられないかと思ってみる。
Link:例外処理
しかし、Android2.1ではC++の例外は使うとまずいっぽい。(使おうとするとコンパイルエラーになる)
使用できるのはAndroid2.2かららしい。
Link:Android NDKでC++の例外を投げるとアプリが落ちる : Happy my life
ということで2.1ベースでいくのであれば普通に例外発行してJavaへ戻すしかなさそう。
プログラムをとめるだけであればFatalErrorというやつを使うととめることが出来る。
しかしなんかこれを使ったら負けな気がする。
Open GL ES 2.0 プログラミングガイド Aaftab Munshi Dan Ginsburg Dave Shreiner アフタブ・ムンシ ダン・ギンズバーグ デーブ・シュライナー 松田 晃一 ピアソン桐原 2009-11-01 |
関連記事