tolua++ 源码分析

tolua++ 源码分析


图中的黑色表示lua table, 灰色表示userdata, 浅灰=》light userdata, 绿色=》内存

tips:

1,  lua里的userdata是一块内存(lua_newuserdata时指定体积),有metatable,但是doesn't have any key。 所以, 每次访问一个usrdata,都一定是到它的metatable里找的。 

2,lightuserdata就是一个指针,没key, 没metatable.

3,  上图中的userdata为什么存的也是c++ instance的内存地址呢。

  因为tolua++就是这么干的,它申请了userdata,并且指定体积是一个指针的大小,然后往这个内存里。  如此而已。

4,tolua++导出来的那些c++对象(或者我们在lua里“new”出来的c++对象),我们在lua里操作,是把它当做一个普通的table的(也就是上图右侧的灰色方块)。如果你做过lua项目的话,你肯定往往这些“table”上写过自定义的属性, 但这也是由tolua++支持的,因为他们是“userdata”,不是table。

-----------------------正文----------------------

  介绍之前,先贴一篇不错的blog,可以作为读tolua++的纲要。

  今天把tolua++源码里的"tolua_pushusertype()"这个函数读了一下,觉得这应该是tolua++里最核心的一个函数了。

扫描二维码关注公众号,回复: 9897649 查看本文章

  顾名思义,就是你给我一个c++实例(value指针所指), 我生成一个与之对应的userdata,并push之

  但这个function完成的功能可不止这些,c++对象与其对应lua userdata的之所以能“对应”,基本就是在这个函数里实现的。

  把这部分源码贴出来吧,自己添了一些注释:

/*@type        correspond to C++ class Name
 *@value     c++ instance pointer
 */
TOLUA_API void tolua_pushusertype (lua_State* L, void* value, const char* type)
{
    if (value == NULL)
        lua_pushnil(L);
    else
    {   /*usually, tolua++ build a correspoding lua table( say class table ) for each Class typein C++
         *now, we just fetch find this table by 'type'( tolua++ already build it somewhere else )
         */ 
        luaL_getmetatable(L, type);                                 /* stack: mt */
        if (lua_isnil(L, -1)) { /* NOT FOUND metatable */
            lua_pop(L, 1);
            return;
        }
        lua_pushstring(L,"tolua_ubox");        /*ubox means  userdata box*/
        lua_rawget(L,-2);                                           /* stack: mt ubox */
        if (lua_isnil(L, -1)) {
            lua_pop(L, 1);
            lua_pushstring(L, "tolua_ubox");
            lua_rawget(L, LUA_REGISTRYINDEX);    /*fetch from global registery, i don't know why either*/
        };
        
        lua_pushlightuserdata(L,value);                             /* stack: mt ubox key<value> */
        lua_rawget(L,-2);                                           /* stack: mt ubox ubox[value] */
        
        if (lua_isnil(L,-1))    /*if hasn't allocate a userdata for it*/
        {
            lua_pop(L,1);                                           /* stack: mt ubox */
            lua_pushlightuserdata(L,value);    
            *(void**)lua_newuserdata(L,sizeof(void *)) = value;     /* stack: mt ubox value newud */
            lua_pushvalue(L,-1);                                    /* stack: mt ubox value newud newud */
            lua_insert(L,-4);                                       /* stack: mt newud ubox value newud */
            /*ubox[ lightuserdata ] = userdata */
            lua_rawset(L,-3);                  /* ubox[value] = newud, stack: mt newud ubox */
            lua_pop(L,1);                                           /* stack: mt newud */
            lua_pushvalue(L, -2);                                   /* stack: mt newud mt */
            /*let the metatable of new userdata refer to 'Class table'*/
            lua_setmetatable(L,-2);                      /* update mt, stack: mt newud */

#ifdef LUA_VERSION_NUM
            lua_pushvalue(L, TOLUA_NOPEER);
            lua_setfenv(L, -2);
#endif
        }
        else    /*i don't care about this branch now*/
        {
            /* check the need of updating the metatable to a more specialized class */
            lua_insert(L,-2);                                       /* stack: mt ubox[u] ubox */
            lua_pop(L,1);                                           /* stack: mt ubox[u] */
            lua_pushstring(L,"tolua_super");
            lua_rawget(L,LUA_REGISTRYINDEX);                        /* stack: mt ubox[u] super */
            lua_getmetatable(L,-2);                                 /* stack: mt ubox[u] super mt */
            lua_rawget(L,-2);                                       /* stack: mt ubox[u] super super[mt] */
            if (lua_istable(L,-1))
            {
                lua_pushstring(L,type);                             /* stack: mt ubox[u] super super[mt] type */
                lua_rawget(L,-2);                                   /* stack: mt ubox[u] super super[mt] flag */
                if (lua_toboolean(L,-1) == 1)                       /* if true */
                {
                    lua_pop(L,3);                                   /* mt ubox[u]*/
                    lua_remove(L, -2);
                    return;
                }
            }
            /* type represents a more specilized type */
            /*luaL_getmetatable(L,type);             // stack: mt ubox[u] super super[mt] flag mt */
            lua_pushvalue(L, -5);                    /* stack: mt ubox[u] super super[mt] flag mt */
            lua_setmetatable(L,-5);                /* stack: mt ubox[u] super super[mt] flag */
            lua_pop(L,3);                          /* stack: mt ubox[u] */
        }
        lua_remove(L, -2);    /* stack: ubox[u]*/
    }
}

发布了56 篇原创文章 · 获赞 10 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/GJQI12/article/details/104923171