參考連結,可將 lua 檔案裡的程式載入到 namespace 裡,好處是可避免各個不同檔案裡出現相同 function 的問題。
稍微針對 C# 做了修改如下:
protected bool load_file_into_namespace(IntPtr L, string S, string N, bool bCall)
{
lua_pushlstring(L, N, N.Length);
lua_gettable(L, (-10002));
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
lua_newtable(L);
lua_pushlstring(L, N, N.Length);
lua_pushvalue(L, -2);
lua_settable(L, (-10002));
}
else
{
if (!lua_istable(L, -1))
{
lua_pop(L, 1);
return (false);
}
}
lua_newtable(L);
lua_pushlstring(L, "_G", 2);
lua_gettable(L, (-10002));
lua_pushnil(L);
while (lua_next(L, -2) != 0)
{
lua_pushvalue(L, -2);
lua_pushvalue(L, -2);
lua_settable(L, -6);
lua_pop(L, 1);
}
if ((luaL_loadfile(L, S) > 0))
{
Console.Write("Error in file " + S + "!\n");
for (int i = 0; ; i++)
if ((lua_isstring(L, i) > 0))
{
Console.Write(lua_tolstring(L, i, IntPtr.Zero) + "\n");
}
else
break;
lua_error(L);
lua_pop(L, 3);
return (false);
}
if (bCall)
lua_call(L, 0, 0);
else
lua_insert(L, -4);
lua_pushnil(L);
while (lua_next(L, -2) != 0)
{
lua_pushvalue(L, -2);
lua_gettable(L, -5);
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
lua_pushvalue(L, -2);
lua_pushvalue(L, -2);
lua_pushvalue(L, -2);
lua_pushnil(L);
lua_settable(L, -7);
lua_settable(L, -7);
}
else
{
lua_pop(L, 1);
lua_pushvalue(L, -2);
lua_gettable(L, -4);
if (!(lua_equal(L, -1, -2) > 0))
{
lua_pushvalue(L, -3);
lua_pushvalue(L, -2);
lua_pushvalue(L, -2);
lua_pushvalue(L, -5);
lua_settable(L, -8);
lua_settable(L, -8);
}
lua_pop(L, 1);
}
lua_pushvalue(L, -2);
lua_pushnil(L);
lua_settable(L, -6);
lua_pop(L, 1);
}
lua_pop(L, 3);
return (true);
}
其中 S 表示檔案路徑, N 表示名稱空間。呼叫名稱空間內的 function 方式也會有些不同:
1) 以 luaL_dostring 方式呼叫:
假設載入的file0.lua 檔如下:
function pp()
print("this is file0");
end
載入的 file1.lua 檔案下:
function pp()
print("this is file1");
end
載入 file0.lua 時設定的 namespace 為 A0,載入 file1.lua 時設定的 namespace 為 A1,載入的程式碼為:
load_file_into_namespace(m_luaState, "file0.lua", "A0", true);
load_file_into_namespace(m_luaState, "file1.lua", "A1", true);
則分別呼叫 file0.lua及file1.lua內的 pp() 函數方式如下:
A0.pp();
A1.pp();
程式碼寫法是:
luaL_dostring(m_luaState, "A0.pp()");
luaL_dostring(m_luaState, "A1.pp()");
2) 以 lua_pcall 方式呼叫(以呼叫
A0.pp() 為例子)
lua_getglobal(m_luaState, "A0");
if (lua_type(m_luaState, -1) == 5)
{
lua_getfield(m_luaState, -1, "pp");
if (lua_type(m_luaState, -1) == 6)
{
// This removes the foo table from the stack
lua_replace(m_luaState, -2);
ret = lua_pcall(m_luaState, 0, 0, 0);
if (ret != 0)
{
lua_pop(m_luaState, 1);
}
}
else
{
lua_pop(m_luaState, 2);
}
}
else
{
lua_pop(m_luaState, 1);
}