ISSを外部から操作するための、スクリプト言語を組込みたくて、Luaについて調査してみた。
第 5 回: Lua を組み込み用の言語として利用する方法 (関数編) — WTOPIA v1.0 documentation
Ubuntuで挑戦したのだが、インストールしたパッケージは以下。
sudo aptitude install lua5.2 liblua5.2-dev
最初コンパイル出来なくて大分いろいろ試したが、C++でコンパイルするときはlua.hppをインクルードしないといけないらしい。
$ cat lua_in_c.cpp #include <stdio.h> #include <lua5.2/lua.hpp> #include <lua5.2/lualib.h> #include <lua5.2/lauxlib.h> int main(int argc, char *argv[]){ const char *fn = "hello.lua"; // Lua の言語エンジンを初期化 lua_State *lua = luaL_newstate(); // Lua のライブラリを使えるようにする luaL_openlibs(lua); // Lua のスクリプトを読み込む printf("%d\n", luaL_dofile(lua, fn)); return 0; } $ cat hello.lua -- hello.lua -- print 関数は自動的に "\n" を入れることを忘れない print("Hello Lua World") print("你好 Lua") print("こんにちは Lua")
これでコンパイルして、実行してみる。
g++ -o call_from_lua call_from_lua.cpp -llua5.2 ./lua_in_c Hello Lua World 你好 Lua こんにちは Lua 0
おお、動いた。
次にやりたいのは、Luaのスクリプト側からC++の関数を呼び出すこと。
cat call_from_lua.cpp /* for_lua.cpp */ #include <stdio.h> #include <lua5.2/lua.hpp> #include <lua5.2/lualib.h> #include <lua5.2/lauxlib.h> /* 足し算を行う関数 */ int c_add(lua_State *L){ // 引数を得る int a1 = lua_tointeger(L, 1); // 第 1 引数を得る int a2 = lua_tointeger(L, 2); // 第 2 引数を得る // 計算 int r = a1 + a2; printf("[%d + %d]\n", a1, a2); // 結果をスタックに戻す lua_pushinteger(L, r); return 1; // 戻り値の数を返す } /* エラーを表示するための関数 */ void show_error(lua_State *L){ const char *err = lua_tostring(L, -1); printf("ERROR: %s\n", err); } /* メイン */ int main(int argc, char *argv[]){ lua_State *L = luaL_newstate(); luaL_openlibs(L); // Lua のライブラリを使えるようにする // Lua に関数を登録する lua_register(L, "c_add", c_add); // Lua のスクリプトを読み込む if (luaL_loadfile(L, "call_c_func.lua") || lua_pcall(L, 0, 0, 0) ){ printf("call_c_func.lua が読めなかった\n"); show_error(L); return -1; } lua_close(L); // 閉じる return 0; }
上記のソースを呼び出す側はこのようにした。
cat call_c_func.lua print (c_add(10, 20))
これでコンパイルして実行する。
g++ -o call_from_lua call_from_lua.cpp -llua5.2 ./call_from_lua [10 + 20] 30
ちゃんと動作した!