CアプリにLuaを埋める
LuaのCモジュールを作るのではなく、CからLuaを使うパターン。
まず、luaの新しいステートを作る。
そのステートで設定ファイル(luaスクリプト)を実行してluaのグローバル値を作る。
最後にluaのスタックを通して、luaのグローバル値を得るという段取りになる。
以前は、JSON形式で3Dのモデル情報を保存するのを画策していたがこっちの方が
luaの文法丸ごと使ってOKなのでよいかもしれぬ。
main.cpp
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <lua.hpp> // lua.hだとリンク時にエラーになる #include <lauxlib.h> #include <lualib.h> class LuaState { lua_State *L_; public: LuaState() { // 新しいLuaステート L_=luaL_newstate(); // Luaに標準関数をオープンする luaL_openlibs(L_); } ~LuaState() { // Luaステートを終了 lua_close(L_); } void error() { fprintf(stderr, "%s\n", lua_tostring(L_, -1)); exit(EXIT_FAILURE); } void error(const char *fmt, ...) { va_list argp; va_start(argp, fmt); vfprintf(stderr, fmt, argp); va_end(argp); exit(EXIT_FAILURE); } void dofile(const char *path) { // Luaスクリプト(チャンク) // をコンパイルしてスタックのトップに関数として積む if(luaL_loadfile(L_, path)){ error(); } // スタックトップの関数を保護モード(エラーが発生したら // エラーコードを返す)で実行する。 if(lua_pcall(L_, 0, 0, 0)){ error(); } } // Luaのグローバル変数をintとして取得する int getInt(const char *key) { // スタックの最初の高さ int top=lua_gettop(L_); // グローバル変数をスタックに乗せる lua_getglobal(L_, key); // Luaの型チェック if(!lua_isnumber(L_, -1)){ error("%s is not number.\n", key); } // スタックトップ(-1)の値をCのintとして取得 int num=lua_tointeger(L_, -1); // スタックを元に戻す lua_settop(L_, top); return num; } // Luaのグローバル変数をstringとして取得する std::string getString(const char *key) { // スタックの最初の高さ int top=lua_gettop(L_); // グローバル変数をスタックに乗せる lua_getglobal(L_, key); // Luaの型チェック if(!lua_isstring(L_, -1)){ error("%s is not string.\n", key); } // スタックトップ(-1)の値をCのintとして取得 const char *str=lua_tostring(L_, -1); // スタックを元に戻す lua_settop(L_, top); return str; } }; int main(int argc, char **argv) { if(argc<2){ fprintf(stderr, "usage: %s {lua script}\n", argv[0]); return 1; } LuaState lua; // スクリプト実行 lua.dofile(argv[1]); // グローバル変数の値を取得 std::cout << "num: " << lua.getInt("num") << std::endl; std::cout << "name: " << lua.getString("name") << std::endl; return 0; }
config.lua
num=150 name="ほげ"
build, execute
$ g++ main.cpp -llua
$ ./a.out config.lua