Squirrel に付属している簡易インタプリタ sq.exe で Squirrel スクリプトを動かしたとき,実行時エラーが発生するとコードのどこを実行した際にエラーが出たのか,またそのときローカル変数がどうだったのかが見られます.
これをゲームに組み込んだ際にも見られるようにしましょう (^ω^)
実行時エラーが起こった際にそれを捕捉する方法も交えて紹介します.
まず,次のようなエラーハンドラと呼ばれる関数を作ります.
/** エラーハンドラ */
#pragma warning (disable : 4702) //return 文への未到達に対する警告を無視
SQInteger handleError(HSQUIRRELVM v)
{
//エラー発生時にはスタックの -1 番目にエラー情報,-2 番目に table (※何かは未調査) …となっている.
const SQChar* desc;
::sq_getstring(v, -1, &desc);
char errorMsg[1024]; //適当に大きくとっておく
sprintf_s(errorMsg, 1024, "%s", desc);
::sqstd_printcallstack(v);
::ScreenFlip(); //こうすることで強制的に表示
MessageBox(NULL, errorMsg, "実行時エラー", MB_OK | MB_ICONEXCLAMATION);
::exit(1);
return 0;
}
後は次のようなコードを実行してやれば,実行時エラーが発生したときにエラーハンドラが実行されるようになります.
//エラーハンドラ設定
//v は SQUIRRELVM
::sq_pushroottable(v); //関数を登録するルートテーブルをスタックに積む
::sq_pushstring(v, _SC("___MyErrorHandler"), -1); //関数名をキーとしてスタックに積む
::sq_newclosure(v, handleError, 0); //新規関数を作成
::sq_newslot(v, -3, SQFalse); //ルートテーブルの新規スロットに関数をセットする
::sq_pop(v, 1); //ルートテーブルの除去
::sq_pushroottable(v); //関数の探索対象テーブル設定する (今回はルートテーブル)
::sq_pushstring(v, _SC("___MyErrorHandler"), -1); //関数名 (キー) の設定
::sq_get(v, -2); //関数のフェッチ,フェッチした関数のスタックへの push
::sq_seterrorhandler(v); //push した関数をエラーハンドラとして設定
::sq_pop(v, 1); //ルートテーブルを除去
色々面倒ですがエラーハンドラの辺りは色々と個性やらアイディアやらを出せそうな感じがするところではあります.即終了とか芸がないよね,とは思いますが私は面倒なのでとりあえずこのままでw
ちなみに,7 行目と 8 行目にルートテーブルを pop してまた push して…という動作がありますが,これは 7 行目までの処理が「関数をバインドする」という一連の動作であり,それをコピペしただけなのでこうなっています.
実際,私の開発環境では最初の pushroottable から 7 行目までの処理を
/**
* C/C++ の関数をバインドする<br />
* (C/C++ の関数を Squirrel VM に登録する (ルートテーブルに登録する))
* @param v Squirrel VM
* @param f 登録する関数の関数ポインタ
* @param fname 関数名
*/
void bindFunction(HSQUIRRELVM v, SQFUNCTION f, const SQChar* fname)
{
::sq_pushroottable(v); //関数を登録するルートテーブルをスタックに積む
::sq_pushstring(v, fname, -1); //関数名をキーとしてスタックに積む
::sq_newclosure(v, f, 0); //新規関数を作成
::sq_newslot(v, -3, SQFalse); //ルートテーブルの新規スロットに関数をセットする
::sq_pop(v, 1); //ルートテーブルの除去
}
という風にサブルーチンに分けています.
(2009-10-30T13:17:02)
手抜きをするなら sqstd_seterrorhandlers がさらに優秀です。
エラー処理は、sqstdaux.cpp あたりのソースを参考にするとよさげかも。
か (2009-10-30T21:44:10)
sqstdaux.cpp の最後の方ですね.読んでみました.
私程度が思いつく事は既に標準で用意されていたということか…ww