zoukankan      html  css  js  c++  java
  • lua和C++交互的lua栈操作——以LuaTinker为例

     一、

     -- 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);
            }
        }
    }
  • 相关阅读:
    后缀自动机在复习
    冬令营模拟day2总结
    割点(模板)
    黑匣子
    挤牛奶
    上白泽慧音
    lca最小公共祖先祖先
    最小花费
    牛的旅行(标程)
    骑马修栅栏
  • 原文地址:https://www.cnblogs.com/yyxt/p/4262500.html
Copyright © 2011-2022 走看看