备忘,备忘。
使用lua_ref来引用变量
int m_nluaFuncRef;
m_nluaFuncRef = lua_ref(L, LUA_REGISTRYINDEX); // 赋值,针对栈顶
lua_getref(L, m_nluaFuncRef); // 调用
lua_unref(L, m_nluaFuncRef); // 释放
遍历table
While traversing a table, do not call lua_tostring directly on a key, unless you know that the key is actually a string. Recall that lua_tostring changes the value at the given index; this confuses the next call to lua_next
lua_pushnil(L);
while (lua_next(L, nIndex))
{
lua_pushvalue(L, -2); //lua_tostring key的时候会改变 key值,会导致遍历有问题,需要保护一下
const char* pszKey = lua_tostring(L, -1);
const char* pszValue = lua_tostring(L, -2);
Params[pszKey] = pszValue;
lua_pop(L, 2);
}
创建table
lua_newtable(L);
for (int nLine = 2; nLine <= nLineCount; nLine++)
{
lua_pushinteger(L, nLine); // key
lua_newtable(L);
for (int nCol = 1; nCol <= nColumnCount; nCol++)
{
lua_pushstring(L, xx->pszKey);
lua_pushstring(L, xx->pszValue);
lua_settable(L, -3);
}
lua_settable(L, -3);
}
table操作
lua_PushObject(g_pUIMgr->m_pluaState, pNode);
lua_pushstring(g_pUIMgr->m_pluaState, CONTROL_KEY_NAME);
lua_gettable(g_pUIMgr->m_pluaState, -2);
nRetCode = lua_type(g_pUIMgr->m_pluaState, -1);
if (nRetCode != lua_TNIL)
{
Log(eLogWarning, "[SetControlName] Redefinition of %s", pszMemberVariableName);
goto Exit0;
}
lua_pop(g_pUIMgr->m_pluaState, 2);
lua_PushObject(g_pUIMgr->m_pluaState, pNode);
lua_pushstring(g_pUIMgr->m_pluaState, pszMemberVariableName);
lua_setfield(g_pUIMgr->m_pluaState, -2, CONTROL_KEY_NAME);
lua_pop(g_pUIMgr->m_pluaState, 1);
Import的lua版本
Import 是我们一直以来对lua文件间访问的封装,它有三个优点:
- 解决文件间的循环依赖
- 每个文件是一个独立的沙盒,不会污染全局变量
- 方便支持热更新
最早的版本用C语言实现的,后来我认为用lua实现更容易理解: (删除了对lua5.1的支持,如有需要可去github查看本文件历史。2016.04.15)
local function GetFileKey(name)
return "FILE:" .. name;
end
function _G.Import(name)
local key = GetFileKey(name);
if _G[key] then
return _G[key];
end
local tb = {};
setmetatable(tb, {__index = _G});
_G[key] = tb;
local fn, msg = loadfile(name, "t", tb);
if not fn then
print(string.format("Import [%s] filed. %s", name, msg));
return _G[key];
end
fn();
return _G[key];
end
function _G.ReImport(name)
local key = GetFileKey(name);
if not _G[key] then
return;
end
local fn, msg = loadfile(name, "t", _G[key]);
if not fn then
print(string.format("Re import [%s] filed. %s", name, msg));
return;
end
fn();
end
setmetatable
5.1的时候metatable只支持userdata,5.2支持table和userdata了
local cmd = setmetatable({}, { __gc = function() print("cmd clear") end })
print "set"
cmd = nil;
collectgarbage();
print "unset"
在5.1下不输出”cmd clear”,5.2下输出。
luajit相关
luajit与lua相比: 优点:
- 可以提高性能
- 可以使用ffi加快开发速度
缺点:
- luajit 在 64 位平台下,只能使用 1G 内存。即使在同一进程内开辟多个 lua state 也不例外。查看代码可以知道,luajit 为了结合更高效的 gc ,使用了自己的内存管理器。这需要用一个 32 位的伪指针工作。为了适应 64 位平台,它强制让分配器分配出来的内存的高位都必须是 0 。所以,多个 lua state 也需要满足这个条件,而不可能突破 4G 的限制。
- luajit 居然使用了 NaN Trick ,这导致 lightuserdata 仅有 48 位有效值(可见 luajit 的源代码 lj_obj.h)。
{…} 不同
function test(...)
local tb = {...}
print(#tb, unpack(tb))
end
test("as", nil, 1,2)
lua 输出
4 as nil 1 2
luajit输出
2 as