tolua++ 源码分析_GJQI12的博客-程序员秘密_tolua 源码

技术标签: lua学习  lua  

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++里最核心的一个函数了。

  顾名思义,就是你给我一个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]*/
    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/GJQI12/article/details/104923171

智能推荐

python 队列实现_python写爬虫如何实现任务队列?_weixin_39569051的博客-程序员秘密

至少三种方法及相应的参考实现:from multiprocessing.dummy import Pool as ThreadPooldef worker(n):return n + 2numbers = range(100)pool = ThreadPool(processes=10)result = pool.map(worker, numbers)pool.close()pool.join(...

loadrunner 场景设计-设置结果文件保存路径_weixin_30402085的博客-程序员秘密

场景设计-设置结果文件保存路径by:授客 QQ:1033553122Results-&gt;Results settingsResults Name结果文件夹名称Directory指定结果文件夹所在目录Automaticallycreate a results directory for each scenario ex...

一则帖子整理:30岁人生困惑,路在何方?_大专求职不知道路在何方_南三方的博客-程序员秘密

以下是一个帖子的全部内容及回复,经常翻翻,用以自励及反思。阅读次数:774,帖子内容如下:      79 年生人,毕业于没落的重点大学大专,学经贸专业,爱好计算机互联网,毕业后先从事业务2年,财务半年,熟悉了肉食、建材商品后,最终还是因爱好从事了网站开发,知识技术全靠自学,从html、dreamweaver、photoshop到css、asp、JavaScript,目前a

原型模式--简单看法和实例_在运行时刻更换原型对象_yatmingli的博客-程序员秘密

1)概述 原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的新的对象。其实就是从一个对象再创建另一个可定制的对象,而且不需要知道任何创建的细节,核心就是克隆。 相似的情形有: 1.鸣人使用影分身之术,一下子出现无数的鸣人来 2.每当市场出现了一款新的iphone手机,各大厂家就会争先去模仿出一模一样的手机出来,只是它们和我们的原来

流的分类_阿离83的博客-程序员秘密

1.按照输入输出分为 输入流 和 输出流2.按照传输单位分为 字节流 和 字符流3.按照功能分为 节点流(低级流) 和 处理流(高级流)还有一种说法是按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.通俗的讲就是 两个端口直接读或者写 数据处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数

随便推点

Spring Security oauth2密码模式和主要组成的配置文件流程图_oauth2密码模式流程图_亦碎流年的博客-程序员秘密

实战可以参考Spring Security OAuth2--密码模式 实战_爱撸铁的程序猿的博客-程序员秘密_oauth2密码模式用户登录

利用AForge+Tesseract制作视频OCR程序_aforge ocr_Hello World,的博客-程序员秘密

先上界面:实现功能及流程:1:从摄像头获取图像,框选要识别的区域2:对选区进行图像处理,方便识别3:识别文字4:获取芯片上的内容(使用客户提供的芯片解码程序)5:比较两个内容是否一致6:写入数据库(带图片)7:对历史数据进行查阅、导出Word(导出时带图片)此版本将4~7功能去除了获取图像:使用AForge组件(参考项目:http

【Stackoverflow好问题】获取完整的堆栈信息_lizeyang的博客-程序员秘密

问题捕获了异常后,如何获取完整的堆栈轨迹(stack trace)精华回答String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e)stackoverflow原址:http://stackoverflow.com/quest

ORACLE11G实战演练--容灾与备份篇(一)_fliks0的博客-程序员秘密

冷备如果条件允许的情况下,可以使用传统冷备操作,步骤十分简单,停止数据库后,将需要备份的数据文件、控制文件、日志文件等拷贝一份即可。热备前提开启归档模式查询一下用户对应关系,我们用SCOTT测试,所在表空间为USERSoracle 查看用户所在的表空间:select username,default_tablespace from dba_users orde...

只有程序员才能看懂的23个段子_php 段子_絮语郭嘉的博客-程序员秘密

01我是一个苦b的轨范员,今晚加班到快今夜了,困得快睁不开眼了,女上司很关怀,问我要不要吃宵夜。我没好气地说,宵夜就算了,能让我睡一觉就行了。女上司红着脸说了句讨厌啊,然后坐在我身边不动,仿佛间隔我很近,搞得我很严峻,莫非她创造我的轨范出了bug?02某人发帖子:“列位JR,我想做一个轨范猿,请问有什么要注意的……”某猿:“等我放工跟你细说……”然后……就没有然后了。0...

评价SAP的PP:PP你认为最强大的是哪部分_ERP资深顾问的博客-程序员秘密

PP你认为最强大的是哪部分?你们现在在用的是哪部分? 我们主要用的是BOM和生产订单.计划策略是sap里面最有搞头的,最后自己配需求类型配出新的策略是粉有成就感的,但是从功能 上讲,sap的pp功能没什么出彩的地方,还是i2强大,i2+sap的sfc才是完美的生产计划与控制, 强烈建议sap废掉apo,收购i2 最强大的是MRP,即物料需求计划,其实PP模块分为计划板块及生

推荐文章

热门文章

相关标签