// main.cc
// C++ 從 Lua 中獲取變量的值. 在 Lua 5.1.4-45 測試通過.
#include <iostream> #include <string> using namespace std; extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" } #pragma comment(lib, "lua5.1.lib") // 這個是 Debug 版.
//#pragma comment(lib, "lua51.lib") // 這個是 Release 版. int main(int argc, char* argv[]) { /************ Init ************/ const string filename = "c:\\users\\songdeming\\main.lua"; lua_State *luaState = luaL_newstate(); // 創建 Lua 狀態. 其實就是一個數據結構. luaL_openlibs(luaState); // 加載所有標准庫, 例如: print 等. if (luaL_loadfile(luaState, filename.c_str()) // 加載文件. 個人認為是將文件編譯, 然后加載到內存. || lua_pcall(luaState, 0, 0, 0)) // 執行全部指令. 這一步必須要進行, 目的是獲取 Lua { // 程序的變量信息, 此后才能通過 getglobal 在棧上定位 cerr <<lua_tostring(luaState, -1) <<endl; // 變量. lua_pop(luaState, 1); return -1; } /************ Variable ************/ cout <<'\t' <<"Get variables..." <<endl;
lua_getglobal(luaState, "a"); cout <<lua_tonumber(luaState, -1) <<endl; lua_getglobal(luaState, "b"); cout <<lua_tostring(luaState, -1) <<endl; // 這里返回的是字符串的地址, 因此不要修改字符串, 也不要在彈出棧后訪問這個地址.
/************ Table ************/ cout <<endl <<'\t' <<"Get table fields..." <<endl;
lua_getglobal(luaState, "t"); lua_pushnumber(luaState, 1); // 獲得無名稱字段. 即 t[1] lua_gettable(luaState, -2); // 從 table 中獲取值的 index 是 -2. cout <<lua_tostring(luaState, -1) <<endl; lua_pop(luaState, 1); lua_pushstring(luaState, "z"); // 獲得有名字段. 即 t['z'] lua_gettable(luaState, -2); // 從 table 中獲取值的 index 是 -2. cout <<lua_tostring(luaState, -1) <<endl; lua_pop(luaState, 1); lua_pop(luaState, 1); // 將 table 出棧. /************ Function ************/ cout <<endl <<'\t' <<"Run function and Get return values..." <<endl;
// 獲取並執行函數. lua_getglobal(luaState, "foo"); // 首先在棧中定位函數. lua_pushnumber(luaState, 999); // 從左向右將參數壓棧. lua_pushstring(luaState, "zzz"); const int paramNum = 2, // 參數數量. retNum = 2; // 返回值數量. if (lua_pcall(luaState, paramNum, retNum, NULL) != 0)// 執行函數. lua_pcall(狀態指針, 參數個數, 返回值個數, 出錯處理函數). 成功返回 0. { cerr <<lua_tostring(luaState, -1) <<endl; lua_pop(luaState, 1); return -1; } // 獲得返回值. // 返回值的壓棧順序是從左向右依次壓棧. 第一個參數最早入棧. for (int i = 1; i <= retNum; ++i) { int type = lua_type(luaState, i); switch (type) { case LUA_TNUMBER: cout <<"LUA_TNUMBER: " <<lua_tonumber(luaState, i) <<endl; break; case LUA_TSTRING: cout <<"LUA_TSTRING: " <<lua_tolstring(luaState, i, NULL) <<endl; break; case LUA_TBOOLEAN: cout <<"LUA_TBOOLEAN: " <<boolalpha <<lua_toboolean(luaState, i) <<endl; break; default : cout <<"unknown: " <<lua_typename(luaState, type) <<endl; break; }//switch }//for // 將返回值出棧. lua_settop(luaState, -retNum);
// TODO: Fetch table returned from function. /************ Close *************/ lua_close(luaState); return 0; }
-- main.lua
-- Lua 作為配置文件.
-- 變量不能設為 local. -- Varaibles. a = 123 b = 'xyz' -- Table. t = {345, 'hello', z = 'uvw'} -- Function. function foo(x, y) print('foo()', x, y) return 1, 'abc' -- TODO: return {...} end
總結來說, 從 C++ 中獲得 Lua 的值, 需要如下 4 步:
1) [必須] lua_getglobal 定位到棧中的變量.
2) [可選] lua_pushnumber/lua_pushstring 設置需要取得哪個字段.
3) [必須] lua_tonumber/lua_tostring 獲得結果.
4) [可選] 如果之前有過 lua_pushxxx 操作, 則需要手工 lua_pop.
