Squirrel その6

すっかり遅くなった Squirrel の話。
今回から数回に分けて組み込みの話をしていきます。
組み込む言語はC/C++を利用します。JAVAC#に組み込む場合はソースを弄ってくださいね。

まず、プロジェクトのリンクライブラリに以下の2つを追加します。

squirrel.lib
sqstdlib.lib

DLしたソースをコンパイルすれば作成されます。
ヘッダファイルは必要なものをインクルードしますが、とりあえず以下のファイルはインクルードしてください。

squirrel.h
sqstdio.h
sqstdaux.h

今回は無難に main() 関数を使用します。適当にメイン関数を作りましょう。
Squirrel は直接実行するのではなく、仮想マシンを作成してその上で実行することになります。
仮想マシンとはCPUなどを積んだ実際のハードウェアではなく、ソフトウェア的に作成された計算機のことを言います。
組み込み系言語は基本的に仮想マシンを利用します。Virtual Machine の頭文字をとって VM と呼ばれることも多いですね。

HSQUIRRELVM v;
v = sq_open(1024);

HSQUIRRELVM が SquirrelVM です。
sq_open() 関数で VM を初期化します。引数は初期スタックサイズです。
通常、スタックサイズは足りなくなれば自動的に増やされます。
ただ、コンシューマゲームなどメモリに制限がある環境では自動的に増やされても困るので、メモリ管理をユーザがするための設定もあるようですが、ここでは割愛します。
このようにして初期化した VM は不要になったら解放しなければなりません。

sq_close(v);

不要になったらこれでOKです。
では、初期化した仮想マシンSquirrel 形式のファイルを実行してみましょう。
Squirrel ファイルとして、以下の行が書かれた test.nut というファイル名のファイルを用意します。

print("Call OK!");

上手くいけば Call OK! という文字列が出力されるわけです。
では、C/C++の方を見ていきましょう。

sqstd_seterrorhandlers(v);
sq_setprintfunc(v, printfunc);

sq_pushroottable(v);
if(SQ_SUCCEEDED(sqstd_dofile(v, _SC("test.nut"), 0, 1))){
    printf("Call Failed!");
}

1行ずつ見ていきましょう。
最初の sqstd_seterrorhandlers() 関数は標準のエラーハンドラを仮想マシンに設定する命令です。
標準のものを使いたくない場合は自分自身で用意することが可能です。
2行目の sq_setprintfunc() は仮想マシンに自作の出力関数をセットする命令です。
こちらも標準の print 命令が存在しているのでそちらを使ってもOKですが、それ以外の出力をしたい場合はこの関数で設定します。
なお、ここで設定している printfunc() 関数は以下のようになります。

void printfunc(HSQUIRRELVM v, const SQChar* s, ...)
{
    va_list arglist;
    va_start(arglist, s);
    vprintf(s, arglist);
    va_end(arglist);
}

この形式の関数なら何でも設定可能です。それこそ、出力命令である必要もなかったりします。
3行目の sq_pushroottable() 関数はルートテーブルを仮想マシンのスタックにプッシュします。
言語仕様の部分でも書いたように、Squirrel には暗黙的なルートテーブルが存在しています。
この命令はそのルートテーブルを設定する命令で、ことあるごとに実行する必要があったりします。それはまたのちほど。
4行目の sqstd_dofile() 関数でファイルの読み込み、及び実行を行います。SQ_SUCCEEDED は関数が正常終了したかどうかをチェックします。
この関数の第1引数は仮想マシン、第2引数は実行するファイル名です。
第3引数は True なら Squirrel ファイルからの戻り値をスタックにプッシュします。
第4引数は True ならエラーが起こった場合にエラーハンドラを呼び出します。
ファイルを実行するだけならこれでOKです。極めて簡単です。
もちろんこれだけではなく、Squirrel ファイル内の関数を呼び出したり、逆に C/C++ の関数を Squirrel から呼び出したりすることができます。
次回はその辺をやっていきたいと思います。