今天繼續學習Lua和C#的互動,今天要講的是載入Lua檔案。 之後的例子都會使用
tolua
來寫,因為tolua提供的lua原生api比xlua更多。
當然你也可以自己編譯lua的dll放到unity裡面。
載入檔案使用的是
luaL_loadfile
這個api,案例如下: 結果是先列印100,再列印200
var
L
=
LuaDLL
。
luaL_newstate
();
var
path
=
Application
。
dataPath
+
“/Examples/02_LoadFile/02。lua”
;
var
errorPath
=
Application
。
dataPath
+
“/02。lua”
;
//返回結果不是0代表載入失敗
var
result
=
LuaDLL
。
luaL_loadfile
(
L
,
path
);
//Debug。Log(result);
if
(
result
!=
0
)
{
Debug
。
LogError
(
LuaDLL
。
lua_tostring
(
L
,
-
1
));
}
if
(
LuaDLL
。
lua_pcall
(
L
,
0
,
0
,
0
)
!=
0
)
{
Debug
。
LogError
(
LuaDLL
。
lua_tostring
(
L
,
-
1
));
}
LuaDLL
。
lua_getglobal
(
L
,
“a”
);
LuaDLL
。
lua_getglobal
(
L
,
“b”
);
if
(
LuaDLL
。
lua_isnumber
(
L
,
-
2
)
==
1
)
{
Debug
。
Log
(
LuaDLL
。
lua_tonumber
(
L
,-
2
));
}
if
(
LuaDLL
。
lua_isnumber
(
L
,
-
1
)
==
1
)
{
Debug
。
Log
(
LuaDLL
。
lua_tonumber
(
L
,-
1
));
}
LuaDLL
。
lua_close
(
L
);
Lua程式碼如下:
a = 100
b = 200
Lua裡面暫時不寫函式,關於函式的呼叫會在之後講。
接下來解釋程式碼:
var
result
=
LuaDLL
。
luaL_loadfile
(
L
,
path
);
//Debug。Log(result);
if
(
result
!=
0
)
{
Debug
。
LogError
(
LuaDLL
。
lua_tostring
(
L
,
-
1
));
}
luaL_loadfile(IntPtr luaState, string filepath)
第一個引數傳入luaState,關於luaState,第一篇文章講了。
第二個引數傳入檔案路徑
。返回值是數字,
如果返回0代表成功,0以外的代表失敗
。 如果路徑是正確的,沒有什麼好說的。
如果是失敗,lua是不會自己報錯的。
出錯時,
lua會把錯誤資訊壓入棧中
,所以需要呼叫
LuaDLL.lua_tostring(L, -1)
把錯誤資訊拿出來。 當傳入錯誤路徑時,錯誤資訊如下:
if
(
LuaDLL
。
lua_pcall
(
L
,
0
,
0
,
0
)
!=
0
)
{
Debug
。
LogError
(
LuaDLL
。
lua_tostring
(
L
,
-
1
));
}
lua_pcall(IntPtr luaState, int nArgs, int nResults, int errfunc)
這個函式的作用是
執行之前載入的lua檔案
,使用
loadfile後lua虛擬機器並不會執行程式碼
,只會編譯程式碼,所以需要呼叫pcall。 lua_pcall包含了四個引數,分別是
luaState,引數個數,返回值個數,錯誤處理函式在棧中的索引
。本篇案例是最簡單的情況,因為Lua程式碼沒有方法,也就沒有引數個數,沒有返回值,我們也不處理錯誤。所以後面三個引數都是0。關於這個方法的複雜情況,以後會講。
另外,
luaL_loadfile
和
lua_pcall
兩步可以直接用
luaL_dofile
替代。
LuaDLL
。
lua_getglobal
(
L
,
“a”
);
LuaDLL
。
lua_getglobal
(
L
,
“b”
);
關於lua的棧
lua的棧是用來處理lua和其它語言互動的部分,並不是lua內部跑的程式碼都在這個棧上
。lua內部有自己的記憶體區用來管理lua自身的程式碼。所以即使執行了lua檔案,lua檔案裡面的公共變數也不是在棧上。
lua_getglobal(IntPtr luaState, string name)
lua_getglobal把lua裡的公共變數壓棧,以便C#端能夠呼叫。上面兩行程式碼的意思是把“a”和“b”分別壓棧。
if
(
LuaDLL
。
lua_isnumber
(
L
,
-
2
)
==
1
)
{
Debug
。
Log
(
LuaDLL
。
lua_tonumber
(
L
,-
2
));
}
if
(
LuaDLL
。
lua_isnumber
(
L
,
-
1
)
==
1
)
{
Debug
。
Log
(
LuaDLL
。
lua_tonumber
(
L
,-
1
));
}
lua_isnumber(IntPtr luaState, int idx)
最後列印結果,lua_isnumber上篇也講了,不過上篇文章用的是xlua,xlua封裝lua原生api的時候把返回值改成bool了,實際上lua原生api是返回int值。
返回1代表true,返回0代表false
。 注意,當呼叫lua_tonumber時
並不會把返回的值出棧
。如果想把棧頂出棧,需要呼叫
LuaDLL.lua_pop(L,1)
。可以嘗試下面的程式碼: 結果是先列印最後入棧的b的值200,再列印a的值100
if
(
LuaDLL
。
lua_isnumber
(
L
,
-
1
)
==
1
)
{
Debug
。
Log
(
LuaDLL
。
lua_tonumber
(
L
,-
1
));
}
LuaDLL
。
lua_pop
(
L
,
1
);
if
(
LuaDLL
。
lua_isnumber
(
L
,
-
1
)
==
1
)
{
Debug
。
Log
(
LuaDLL
。
lua_tonumber
(
L
,-
1
));
}
那麼這次的內容就這些了, github工程地址對應的是
Example/02_LoadFile
資料夾。
系列文章:
【Lua與C#互動①】Lua中的棧_lua_水雞的遊戲開發學習筆記-CSDN部落格
【Lua與C#互動②】載入Lua檔案_lua_水雞的遊戲開發學習筆記-CSDN部落格
【Lua與C#互動③】方法呼叫和錯誤處理函式_水雞的遊戲開發學習筆記-CSDN部落格
qq群:891809847