码迷,mamicode.com
首页 > 其他好文 > 详细

Lua中Userdata类型源码实现

时间:2015-04-15 19:34:53      阅读:554      评论:0      收藏:0      [点我收藏+]

标签:

    1、概述
    Lua中userdata分两种,一种是轻量级userdata(light userdata),轻量级userdata是一种表示C指针的值,对Lua虚拟机来说,这种数据类型不需要GC(垃圾回收),其指向的内存由用户分配和释放,其实现就是一个void *p指针;后一种userdata类型完全userdata(full userdata),内存是由Lua虚拟机分配,并有GC机制负责处理。下面将通过Lua 5.2.1的源码来看后一种userdata的实现。
    2、源码实现

    userdata内存存储形式类似于字符串,以一个头开始然后紧随头后面保存相关的数据,但是每个userdata都拥有自己独立的元表。下面是userdata对应的头数据结构Udata代码(lobject.h):

431 /*                                                                                                 
432 ** Header for userdata; memory area follows the end of this structure                              
433 */                                                                                                 
434 typedef union Udata {                                                                              
435   L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */                            
436   struct {                                                                                         
437     CommonHeader;                                                                                  
438     struct Table *metatable;                                                                       
439     struct Table *env;                                                                             
440     size_t len;  /* number of bytes */                                                             
441   } uv;                                                                                            
442 } Udata;

成员dummy和CommonHeader含义与TString完全一样。其他成员含义如下:
    struct Table *metatable:指向userdata对应的元表,也就是一个table。可以调用luaL_newmetatable创建一个元表(注意是在注册表上创建的,也就是说userdata的元表保存在注册表中),然后调用lua_setmetatable来设置userdata的元表,注意Lua代码中不能改变userdata的元表。
    struct Table *env:userdata的环境,创建userdata时该值为NULL。可以通过调用lua_setuservalue函数来设置userdata的环境。
    size_t len:保存userdata内存的大小,就紧随头后面数据内存的大小。
userdata的数据部分和字符串一样,都是紧接着放在结构后面,创建userdata的代码如下(lstring.c):

175 Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {                                          
176   Udata *u;
177   if (s > MAX_SIZET - sizeof(Udata))
178     luaM_toobig(L);
179   u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u;                               
180   u->uv.len = s;
181   u->uv.metatable = NULL;
182   u->uv.env = e;
183   return u;                                                                                        
184 }  
    3、总结
    I、
lua中的userdata类型主要用来表示在C/C++中定义的类型,即用来实现扩展lua,这些扩展代码通常是用C/C++来实现的。对lua 虚拟机来说userdata只是提供了一块原始的内存区域,可以用来存储任何东西,并且在lua中userdata没有任何预定义的操作。注意这块分配的额外内存是由Lua垃圾收集器来管理的,无须关心起释放等情况。
    II、userdata的元表通常用来存储对应C/C++类型的方法,这样在脚本中可以直接调用userdata对应的方法,并且这些方法也是用C/C++实现的。
    III、创建一个新的userdata时,其环境表默认值是空,即成员值env 为NULL,当前这个成员在Lua没被使用。在一些文章指出,这个成员可以保存与userdata实例相关的数据,而其对应的元表保存userdata的方法。

参考资料

Lua 5.2.1源码
《Lua程序设计》(第二版)

Lua中Userdata类型源码实现

标签:

原文地址:http://blog.csdn.net/maximuszhou/article/details/45063619

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!