FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

C++内でLuaをインタプリタのように動作させるための調査(実装してみた)

前回の続きで、LuaインタプリタISSに実装してみた。

msyksphinz.hatenablog.com

前回lua_interpreterを実行してみて、バックスペースなどの操作が出来なかったのだが、これはlibreadlineを使っていなかったからだった。 コンパイルするときに、-DLUA_USE_READLINEを追加することでBSやAltなどが使用可能になる。

gcc -o lua_interpreter lua_interpreter.c -llua5.2 -lreadline -DLUA_USE_READLINE

という訳で、ISSインタプリタのモードを追加する。

github.com

とりあえずは、luaモードになったときは、os.exit()が呼ばれない限りはシミュレーション終了後にインタプリタモードに入ることにした。 そのためみ、Luaの実行関数から抜けても、インタプリタを出すようにする。luaのソースから引っ張ってくるならば、dotty()を実行することでこれが可能になる。

     if (!FLAGS_script.empty()) {
-        ExecuteFromFile (FLAGS_script);
-
+        lua_State *lua_state = SetupLuaEnv ();
+        ExecuteFromFile (lua_state, FLAGS_script);
+        dotty (lua_state);
+    } else if (!is_cmd_binfile && !is_cmd_srecfile && !is_cmd_imgfile) {
+        lua_State *lua_state = SetupLuaEnv ();
+        dotty (lua_state);

という訳で、ExecuteFromFile() がLuaスクリプトを実行する関数で、この関数を抜けてもdotty()が実行されるようになる。

それ以外にも、特に実行ファイルが指定されなければ、Luaスクリプトが呼ばれるようにした。 LuaC++の中で使う場合は、まずはlua_state構造体をインスタンスして、それに対して処理を実行しなければならない。例えば、lua_stateにC++の関数を登録するためには、以下のようにする。

lua_State* SetupLuaEnv (void)
{
    lua_State *lua_state = luaL_newstate ();
    luaL_openlibs (lua_state);

    // Register Functions
    lua_register (lua_state, "make_core", Lua_MakeCore);
    lua_register (lua_state, "run", Lua_Run);
    lua_register (lua_state, "set_pc", Lua_SetPC);
    lua_register (lua_state, "set_max_cycle", Lua_SetMaxCycle);
    lua_register (lua_state, "load", Lua_LoadBin);
    lua_register (lua_state, "debug", Lua_SetDebug);
    lua_register (lua_state, "get_step", Lua_GetStep);
    lua_register (lua_state, "get_addr", Lua_GetAddr);
    lua_register (lua_state, "set_pcbreak", Lua_SetPCBreak);
    lua_register (lua_state, "get_reg", Lua_GetReg);
    lua_register (lua_state, "get_mem", Lua_GetMem);
    lua_register (lua_state, "dump_regs", Lua_DumpRegs);
    lua_register (lua_state, "skip_hier", Lua_SkipHier);

    return lua_state;
}

Luaを処理する各関数には、殆どの場合このlua_stateを殆どの場合追加する。そのあたりは、複数Luaインタプリタを立ち上げたりするときの構造が非常にしっかりしている印象だ。 一方で、Pythonの場合はそのあたりが暗黙的になっているというか、構造体などを指定しなくても一つの環境にいろいろ追加されていくから、ちょっと厳密ではないが、取っ付きやすくはある。

Py_Main(argc, argv);   // 環境構造体を指定する必要がない

ともかく、これでLuaインタラクティブに実行できるようになった!