僕のISSはインタプリタとしてLuaを使用しているが、起動時にLuaファイルを指定するとそこから一方的に実行が始まるだけで、例えばデバッグモードのように一旦停止してレジスタをダンプする、などの動作を挿入することができない。 そのような動作は、全てスクリプトに予め書いておかなければならないのだ。 これは不便なので、Luaを利用してどのようにそれを実現するのかを調査してみた。
一方、Pythonの場合は前の記事に書いた、Py_Main()を利用すればいいということは分かっている。Luaでも、同じことができるはずだ。
いろいろ調査していった結果、まずはLuaのソースコードを参照するのが手っ取り早いということが分かってきた。 まずは、Lua5.2のソースコードを読んで、何が起きているのかを見てみよう。
ソースコードにはmain()が挿入されているが、キモになるのは、引数が何も指定されていなかった場合、これは条件分岐を追い掛けていくと、
static int pmain (lua_State *L) { int argc = (int)lua_tointeger(L, 1); char **argv = (char **)lua_touserdata(L, 2); int script; int args[num_has]; args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0; if (argv[0] && argv[0][0]) progname = argv[0]; script = collectargs(argv, args); if (script < 0) { /* invalid arg? */ print_usage(argv[-script]); return 0; } if (args[has_v]) print_version(); if (args[has_E]) { /* option '-E'? */ lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); } /* open standard libraries */ luaL_checkversion(L); lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ luaL_openlibs(L); /* open libraries */ lua_gc(L, LUA_GCRESTART, 0); if (!args[has_E] && handle_luainit(L) != LUA_OK) return 0; /* error running LUA_INIT */ /* execute arguments -e and -l */ if (!runargs(L, argv, (script > 0) ? script : argc)) return 0; /* execute main script (if there is one) */ if (script && handle_script(L, argv, script) != LUA_OK) return 0; if (args[has_i]) /* -i option? */ dotty(L); else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */ if (lua_stdin_is_tty()) { print_version(); dotty(L); } else dofile(L, NULL); /* executes stdin as a file */ } lua_pushboolean(L, 1); /* signal no errors */ return 1; }
dotty()という関数を呼んでいることが分かる。また、これは同様に-iオプションでも動作することが分かった。
これをコンパイルして、実行してみよう。このソースをそのままダウンロードして、コンパイルしてみる。 ちなみに、Ubuntuで実行した場合は、includeの位置をちょっと書き換えてやる必要があった。
#include "lua5.2/lua.h" #include "lua5.2/lauxlib.h" #include "lua5.2/lualib.h"
さらに、g++(C++)でコンパイルするときは、lua.hではなくlua.hppを使うように変更する。
#include "lua5.2/lua.hpp" #include "lua5.2/lauxlib.h" #include "lua5.2/lualib.h"
gcc lua_interpreter.c -o lua_interpreter -llua5.2 ./lua_interpreter Lua 5.2.3 Copyright (C) 1994-2013 Lua.org, PUC-Rio > print 'Hello' Hello >
お、いいね。インタフェースも分かったし、次はこれをISSに移植してみよう。