您的位置:首页 > 编程语言 > Lua

lua和C++交互的lua栈操作——以LuaTinker为例

2015-01-30 15:38 302 查看
一、

-- C++类注册函数(LuaTinker) 的lua栈操作:

--    lua栈内容(执行到pop语句)            栈地址        <--执行语句
space_name[name] = t1                      -- (2b8)     -- lua_rawset(L, -4);
-- t1[__gc] = destroyer<T>                  -- (2d8)     -- lua_rawset(L, -3);
-- destroyer<T>                              -- (2f8)     -- lua_pushcclosure(L, destroyer<T>, 0);
-- __gc                                      -- (2e8)     -- lua_pushstring(L, "__gc");
-- t1[__newindex] = meta_set              -- (2d8)     -- lua_rawset(L, -3);
-- meta_set                                  -- (2f8)     -- lua_pushcclosure(L, meta_set, 0);
-- __newindex                              -- (2e8)     -- lua_pushstring(L, "__newindex");
-- t1[__index] = meta_get                  -- (2d8)     -- lua_rawset(L, -3);
-- meta_get                                  -- (2f8)     -- lua_pushcclosure(L, meta_get, 0);
-- __index                                  -- (2e8)     -- lua_pushstring(L, "__index");
-- t1[__name] = name                      -- (2d8)     -- lua_rawset(L, -3);
-- name                                   -- (2f8)     -- lua_pushstring(L, name);
-- __name                                  -- (2e8)     -- lua_pushstring(L, "__name");
-- setmetatable(t1, t2)                  -- (2d8)     -- lua_setmetatable(L, -2);
-- t2[__index] = static_meta_get         -- (2e8)     -- lua_rawset(L, -3);
-- static_meta_get                        -- (308)     -- lua_pushcclosure(L, static_meta_get, 0);
-- __index                                -- (2f8)     -- lua_pushstring(L, "__index");
-- t2                                      -- (2e8)     -- lua_newtable(L);
-- t1                                      -- (2d8)     -- lua_newtable(L);
-- name                                 -- (2c8)     -- lua_pushstring(L, name);
-- space_name[name]                     -- (2b8)     -- lua_rawget(L, -2);
-- name                                 -- (2b8)     -- lua_pushstring(L, name);
space_name                                 -- (2a8)     -- push_meta(L, space_name::name);
L                                           -- (298)     -- 初始状态


-- C++类注册函数(LuaTinker),支持注册到命名空间namespace

template<typename T>
void class_addEx(lua_State* L, const char* name)
{
push_meta(L, space_name::name());
if(lua_istable(L, -1))
{
class_name<T>::name(name);

lua_pushstring(L, name);
lua_rawget(L, -2);
if (!lua_istable(L, -1))
{
lua_pushstring(L, name);
lua_newtable(L);

lua_newtable(L);
lua_pushstring(L, "__index");
lua_pushcclosure(L, static_meta_get, 0);
lua_rawset(L, -3);
lua_setmetatable(L, -2);

lua_pushstring(L, "__name");
lua_pushstring(L, name);
lua_rawset(L, -3);

lua_pushstring(L, "__index");
lua_pushcclosure(L, meta_get, 0);
lua_rawset(L, -3);

lua_pushstring(L, "__newindex");
lua_pushcclosure(L, meta_set, 0);
lua_rawset(L, -3);

lua_pushstring(L, "__gc");
lua_pushcclosure(L, destroyer<T>, 0);
lua_rawset(L, -3);

lua_rawset(L, -4);
}
}
lua_pop(L, 2);
}


二、

-- meta_get栈操作如下:
--    lua栈内容            栈地址        <--执行语句
t_meta[__index]            -- (ed8)     -- lua_rawget(L,-2); <-- 执行到此语句
-- __index                 -- (ed8)     -- lua_pushvalue(L,2);
t_meta                     -- (ec8)     -- lua_getmetatable(L,1);
__index                    -- (eb8)     -- 初始 lua_pushstring(L, "__index");
t                         -- (ea8)     -- 初始
L                         -- (e98)     -- 初始状态


--// int lua_tinker::meta_get(lua_State *L)
int lua_tinker::meta_get(lua_State *L)
{
lua_getmetatable(L,1);

lua_pushvalue(L,2);
lua_rawget(L,-2);

bool is_dispatcher = false;
const char* func_name = lua_tostring(L, 2);

if(lua_isuserdata(L,-1))
{
user2type<var_base*>::invoke(L,-1)->get(L);
lua_remove(L, -2);
}
else if (lua_istable(L, -1))
{
lua_remove(L, -1);
is_dispatcher = true;
}
else if (lua_isnil(L, -1))
{
lua_remove(L, -1);
invoke_parent(L, func_name);
if (lua_isnil(L, -1))
{
lua_remove(L, -1);
invoke_child(L, func_name);
}
if (lua_istable(L, -1))
{
lua_remove(L, -1);
is_dispatcher = true;
}
}

//函数分发
if (is_dispatcher)
{
push_currfuncname(L, func_name);

push_dispatcher(L);
}

lua_remove(L,-2);

return 1;
}


三、

--> 假设:meta_get函数执行到上面语句(栈内容如上) ——> t_meta[__index] == nil ——> 进入invoke_parent(L, func_name);

--    lua栈内容                栈地址        <--执行语句
tt[funcname]                -- (e18)     -- lua_remove(L, -2);
-- tt[funcname]                -- (e28)     -- lua_rawget(L, -2); -->lua_istable(L, -1) || lua_isfunction(L, -1)
-- funcname                    -- (e28)     -- lua_pushstring(L, funcname);
-- t_meta[__parent] = tt    -- (e18)     -- lua_rawget(L, -2); --> lua_istable(L,-1),重命名为tt
-- __parent                    -- (e18)     -- lua_pushstring(L, "__parent");
--                             -- (e08)     -- lua_remove(L, -1);
-- t_meta[__index]            -- (e18)     -- lua_rawget(L,-2);
t_meta                         -- (d08)     -- lua_getmetatable(L,1);
__index                        -- (cf8)     -- 初始 lua_pushstring(L, "__index");
t                             -- (ce8)     -- 初始
L                             -- (cd8)     -- 初始状态(和上面的栈内容不匹配,因为是另一个过程,其满足t_meta[__index] == nil)


// static void invoke_parent(lua_State *L, const char* funcname)

static void invoke_parent(lua_State *L, const char* funcname)
{
lua_pushstring(L, "__parent");
lua_rawget(L, -2);
if(lua_istable(L,-1))
{
lua_pushstring(L, funcname);
lua_rawget(L, -2);

if (lua_istable(L, -1) || lua_isfunction(L, -1))
{
lua_remove(L, -2);
}
else
{
lua_remove(L, -1);
invoke_parent(L, funcname);
lua_remove(L, -2);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: