@[TOC] 关于lua中userdata的理解
关于Userdata的理解
Userdata数据结构
- userdata是用来存放用户自定义数据结构的实列,userdata的类型有两种类型,分别是lightuserdata,和fulluserdata。lightuserdata是value结构中的一个变量类型,本质上是一个void*指针:
// luaobject.h
typedef union lua_Value{
struct GCObject* gc;
void* p;
int b;
lua_Integer i;
lua_Number n;
lua_CFunction f;
} Value;
light userdata的内存,需要用户自行管理,而fulldata则是通过lua的gc机制进行管理,本章主要讲fulluserdata,所有的userdata均为full userdata。
对full userdata的操作实现,一般在C层进行的,后面会有例子
userdata的数据结,在dummylua中,定义如下所示:
//luaobject.h
#define CommonHeader struct GCObject* next ;lua_byte tt_ ;lu_byte marked
typedef struct Udata {
CommonHeader; //GC公共头部
struct Table* metatable; //userdata 可以设置metatable,一般用于设置_gc域,在userdata被回收之前,
//__gc函数会被调用,一般用于回收系统资源
int ttuv_; //相当于Tvalue 的tt_,用来指代user_变量的类型
int len; // 自定义域的大小
Value user_; //本质就是Tvalue的value_的value部分,这里将TValue拆分成了两个部分
}Udata;
UserData的接口
分别是Lua_newuserdata.getudatamem,setuservalue.getuservalue。
luaS_newuserdata的定义:
//luastring.c
udata* luaS_newuserdata(struct lua_State* L,int size);
这个接口,就是创建了一个userdata实例,这个userdata实例的大小就是Udata头部+传入的size大小,我们可以看一下实例的构成:
±-------------------±------------------+
|Header:Udata | user domain |
±-------------------±-----------------+
前面的Header,就是sizeof(Udata)的大小,而后面的user domain,则是luaS_newuserdata的第二个参数size来指定,比方,现在我们定义了一个Vector3的数据结构:
typedef struct Vector3 {
float x;
float y;
float z;
}Vector3;
要创建时,这个Vector3 关联的userdata。那么它的创建代码则如下所示:
Udata* u = luaS_newuserdata(L,sizeof(Vector3));
第二个参数,size的大小则是sizeof(vector3)的大小,也就是12,那么此时,user domain的大小则为12byte的大小。
在完成了userdata实例的创建之后,要在C层获取我们自定义的结构实例的指针,此时需要一个接口getudatamem.
#define getudatamem(o) (cast(char*,o)+sizeof(Udata))
这个宏的作用在。则是将userdata实例中,user domain部分的指针拿到,获取的结果所指向的位置,如下’ ^ '所示:
±-------------------±------------------+
|Header:Udata | user domain |
±-------------------±-----------------+
^
通过这个宏,我们可以获取结构自定义结构变量的实例,具体方法如下所示:
Vector3* v3 = (vector3*)getudatamem(u);
接下来,就可以对V3所指向的内存块进行对应的处理了.
userdata 还有一个重要的接口,就是setuserdata,这是一个宏,它的作用是将一个Tvalue实例赋值到Udata头部中,分别将TValue实例的tt__赋值给Udata的ttuv_,将TValue的value_赋值给Udata的user_字段中,其定义如下所示:
//luaobject.h
#define setuservalue(u ,o)\
(u) ->ttuv_ = (O) ->tt_;(u) ->user_=(o)->value_
luaobject.h