隨著 Qtun 專案功能迭代,可配置參數日益增多。C 語言處理字串與複雜配置解析能力較弱,團隊決定引入輕量級 Lua 腳本語言作為配置載體,同時為未來第三方插件系統奠基。
script_global_init在 init_lua 階段調用,註冊標準庫並綁定 Qtun 內部物件:
int script_global_init(lua_State* lua) {
load_lib(lua, "_G", luaopen_base); // 基礎庫
load_lib(lua, LUA_TABLIBNAME, luaopen_table); // table 庫
load_lib(lua, LUA_STRLIBNAME, luaopen_string); // string 庫
load_lib(lua, LUA_IOLIBNAME, luaopen_io); // io 庫
// 註冊 C 函數供 Lua 調用
lua_pushcfunction(lua, _syslog);
lua_setglobal(lua, "_syslog");
// 將 C 結構體映射到 Lua 表(透過 metatable)
init_qtun_state(lua); // qtun.state
init_qtun_conf(lua); // qtun.conf
init_qtun_log(lua); // qtun.log (僅定義日誌等級常數)
return 1;
}
關鍵點:qtun.state 和 qtun.conf 透過 metatable 實現 C 物件到 Lua 表的雙向映射;qtun.log 僅暴露常數。
script_load_config調用 Lua 腳本 scripts/load_config.lua 解析配置文件:
int script_load_config(lua_State* lua, library_conf_t* conf, const char* file_path) {
char path[MAX_PATH];
lua_pushlightuserdata(lua, conf);
lua_setglobal(lua, "__conf__"); // 傳遞 C 結構體指標給 Lua
strcpy(path, qtun->this_path);
strcat(path, "scripts/load_config.lua");
if (luaL_dofile(lua, path) != 0) {
fprintf(stderr, "%s\n", lua_tostring(qtun->lua, -1));
lua_close(qtun->lua);
exit(1);
}
return 1;
}

三個核心腳本分工明確:
load_config.lua:入口腳本,解析配置文件路徑,調用解析器parser.lua:實際配置項解析邏輯,填充 __conf__ 結構體validator.lua:配置合法性驗證,確保必要參數存在且類型正確嵌入 Lua 使 Qtun 實現了:
完整代碼可參考專案 step14 目錄。