上篇文章已經寫到過整體環境的配置和給了份完整的代碼,下面這篇文章是來對每個語句進行一個簡單的剖析:
在ladd函數中執行了lua中的add函數,首先看lua_getglobal函數:
void lua_getglobal (lua_State *L, const char *name);
把全局變量 name 裏的值壓入堆棧。這個是用一個宏定義出來的:
#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s)
這裏lua_getglobal(L, “add”)把add函數壓入堆棧,接着把x和y參數壓入堆棧,然後調用lua_call執行add函數,關於lua_call函數:
void lua_call (lua_State *L, int nargs, int nresults);
它的功能是調用一個函數,需要遵循以下協議:
首先,要調用的函數應該被壓入堆棧;
接着把需要傳遞給這個函數的參數按正序壓棧; 這是指第一個參數首先壓棧。
最後調用一下lua_call; nargs 是你壓入堆棧的參數個數。 當函數調用完畢後,所有的參數以及函數本身都會出棧。 而函數的返回值這時則被壓入堆棧。 返回值的個數將被調整爲 nresults 個, 除非 nresults 被設置成 LUA_MULTRET。 在這種情況下,所有的返回值都被壓入堆棧中。 Lua 會保證返回值都放入棧空間中。 函數返回值將按正序壓棧(第一個返回值首先壓棧), 因此在調用結束後,最後一個返回值將被放在棧頂。
這裏lua_call(L, 2, 1)是指函數有兩個參數和一個返回值。
lua_tointeger(L, -1):表示從棧頂取得返回值。
lua_pop(L, 1):表示從堆棧中彈出一個元素,因爲此時add函數已經執行完畢,參數和函數本身已經出棧,堆棧中只有返回值。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//新建虛擬機
lua_State *L = luaL_newstate();
//載入庫
luaL_openlibs(L);
//這裏執行 test.lua Lua文件
luaL_dofile(L, "test.lua"); //填的是絕對路徑
//獲取 返回結果
lua_getglobal(L,"test");
printf("\n%s\n", lua_tostring(L, -1));
//一定記得關閉虛擬機
lua_close(L);
return 0;
}
//待Lua調用的C註冊函數
static int add2(lua_State* L)
{
//檢查棧中的參數是否合法,1表示Lua調用時的第一個參數(從左到右),依此類推。
//如果Lua代碼在調用時傳遞的參數不爲number,該函數將報錯並終止程序的執行。
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
//將函數的結果壓入棧中。如果有多個返回值,可以在這裏多次壓入棧中。
lua_pushnumber(L,op1 + op2);
//返回值用於提示該C函數的返回值數量,即壓入棧中的返回值數量。
return 1;
}
//待Lua調用的C註冊函數。
static int sub2(lua_State* L)
{
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
lua_pushnumber(L,op1 - op2);
return 1;
}
//待Lua調用的C註冊函數。
static int l_sin (lua_State *L) {
double d = lua_tonumber(L, 1); /* get argument */
lua_pushnumber(L, sin(d)); /* push result */
return 1; /* number of results */
}
int _tmain(int argc, _TCHAR* argv[])
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
//將指定的函數註冊爲Lua的全局函數變量,其中第一個字符串參數爲Lua代碼
//在調用C函數時使用的全局函數名,第二個參數爲實際C函數的指針。
lua_register(L, "add2", add2);
lua_register(L, "sub2", sub2);
lua_register(L, "l_sin", l_sin);
//在註冊完所有的C函數之後,即可在Lua的代碼塊中使用這些已經註冊的C函數了。
luaL_dofile(L,"test.lua"); //絕對路徑名
//if (luaL_dostring(L,testfunc))
// printf("Failed to invoke.\n");
//const char *buf = "print('Hello World')";
//luaL_dostring(L,buf);
lua_close(L);
return 0;
}
test.lua
function show()
print("helloworld")
print(add2(1.0,2.0))
print(sub2(20.1,19))
print(l_sin(1))
end
show()
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------