1. 程式人生 > >Lua檔案函式呼叫

Lua檔案函式呼叫


假設你在指令碼中定義了一個函式:

function main(number)
number = number + 1
return number
end

在你的遊戲程式碼中,你希望在某個時刻呼叫這個函式取得它的返回值。

在Lua中,函式等同於變數,所以你可以這樣來取得這個函式:

lua_getglobal(L, "main");//函式現在棧頂

現在,我們可以呼叫這個函式,並傳遞給它正確的引數:

lua_pushnumber(L, 100); //將引數壓棧
lua_pcall(L, 1, 1, 0); //呼叫函式,有一個引數,一個返回值
//返回值現在棧頂
int result = lua_tonumber(L, -1);

result 就是函式的返回值

完整的測試程式碼如下:

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

int main(int argc, char *argv[])
{
lua_State *L = lua_open();
luaopen_base(L);

const char *buf = "function main(number) number = number + 1 return number end";

lua_dostring(buf);

lua_getglobal(L, "main");
lua_pushnumber(L, 100);
lua_pcall(L, 1, 1, 0);

int result = lua_tonumber(L, -1);

assert(result == 101);

lua_close(L);

return 0;
}

lua_pcall()函式

lua_State* L = luaL_newstate();
luaL_openlibs(L);
/*l_opentestlib(L);*/
register_api(L);

if(luaL_dofile(L, "formula/test/testreal.lua") != 0)
     LuaVMError(L,"luaL_dofile formula/test/testreal.lua error\n");

LuaVMstackDump(L);
   
if(lua_pcall(L,0,1,0) != 0)
    LuaVMError(L,"lua_pcall failed:%s\n",lua_tostring(L,-1));
   
printf("OK, Billing realfee is %ld\n",lua_tointeger(L,-1));
lua_pop(L,1);
lua_close(L);
出現的錯誤一直是:
lua_pcall failed:attempt to call a nil value

其實是由於理解錯誤造成的,因為只有在呼叫lua函式的時候才用lua_pcall(),官方文件如下:

可以呼叫lua_pcall時指定引數的個數和返回結果的個數。第四個引數可以指定一個錯誤處理函式,我們下面再討論它。和Lua中賦值操作一樣,lua_pcall會根據你的要求調整返回結果的個數,多餘的丟棄,少的用nil補足。在將結果入棧之前,lua_pcall會將棧內的函式和引數移除。如果函式返回多個結果,第一個結果被第一個入棧,因此如果有n個返回結果,第一個返回結果在棧中的位置為-n,最後一個返回結果在棧中的位置為-1。

如果lua_pcall執行時出現錯誤,lua_pcall會返回一個非0的結果。另外,他將錯誤資訊入棧(仍然會先將函式和引數從棧中移除)。在將錯誤資訊入棧之前,如果指定了錯誤處理函式,lua_pcall會掉用錯誤處理函式。使用lua_pcall的最後一個引數來指定錯誤處理函式,0代表沒有錯誤處理函式,也就是說最終的錯誤資訊就是原始的錯誤資訊。否則,那個引數應該是一個錯誤函式被載入的時候在棧中的索引,注意,在這種情況下,錯誤處理函式必須要在被呼叫函式和其引數入棧之前入棧。

對於一般錯誤,lua_pcall返回錯誤程式碼LUA_ERRRUN。有兩種特殊情況,會返回特殊的錯誤程式碼,因為他們從來不會呼叫錯誤處理函式。第一種情況是,記憶體分配錯誤,對於這種錯誤,lua_pcall總是返回LUA_ERRMEM。第二種情況是,當Lua正在執行錯誤處理函式時發生錯誤,這種情況下,再次呼叫錯誤處理函式沒有意義,所以lua_pcall立即返回錯誤程式碼LUA_ERRERR。