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  | 








関連記事