userdata属性,数据类型之UserData
前言
本文将讲解Lua与其它编程语言(例如C语言,C++语言等)交互时常常需要使用的变量类型,分别为UserData和LightUserData,我们日常开发的时候如果只使用Lua一种编程语言,则这部分内容平时应该接触得会比较少。
交互:指不同编程语言间可以互相调用。在Lua中,与其它编程语言的调用是利用堆栈完成的,一种编程语言把内容放在栈上(一片内存区域),另一种编程语言根据定义好的数据格式解释栈上的二进制数据内容为本语言的数据结构。
定义
UserData:又有名字叫Full User Data,全量级的用户数据。通常是一块内存区域,可用于转换为特殊的数据结构,UserData内部数据的解析与设置由使用者自己进行实现,Lua并没有能力处理这份二进制内存,Lua只负责这块内存区域的内存管理与回收。
LightUserData: 轻量级用户数据,相比于上面的FullUserData,它是轻量的,它只是一个指针,在C语言中对应的类型为void*,占4或8个字节,Lua也不会管理这个指针的内存,全由使用者自己管理。
本文上半部分会讲解UserData,下半部分会讲解LightUserData。
UserData用例
我们先看UserData类型的使用方式,Lua的源码是用C语言写的,我们在本文中也将选择C语言作为与Lua交互的语言。
我们举个例子开始学习,我们在C语言中定义了如下结构体:
struct People{ string name; int age;}
为了能在Lua中使用这个结构体,我们这里就可以使用UserData。我们看下面这段C语言代码就是创建了一个UserData对象并插入到Lua堆栈顶部:
static int People(lua_State *L){ struct People *pPeople = (struct People *)lua_newuserdata(L, sizeof(struct People)); //设置pPeople对象的元表 // ...........(暂时省略) return 1; // 新的userdata已经在栈上了}
接下来就可以在Lua中创建一个People对象并打印其名字:
local people = People.New()print(people.name)
上面这个例子看着简单,其实我把C语言函数导出,元表设置相关的代码都省略了,本章中我们后面会再详细讲,这里先对与C语言交互简单有个印象就好了。
接下来我们就开始UserData的源码学习吧。
UserData类型定义
见源码《lua.h》,类型枚举为LUA_TUSERDATA,数值为7,二进制8位为0000 0111:
接下来看下图红框1部分,可知USERDATA类型只是单纯声明了一个LUA_VUSERDATA类型变体作为类型别名,没有声明多余的其它类型变体:
上图红框2,3表示UserData也可以看作为GCObject的子类,这些类在判断变量是否合法的时候都会使用ctb宏,只有满足ctb宏IS_COLLECTABLE(第7位为1)才是合法的对象。所以一个合法的UserData类型的类型标识(type tag)8位二进制为0100 0111。
红框3中代码val_(o).gc表示UserData数据存于gc指针指向的地址上:
gco2u(GCObject*)函数则把该指针转换为真正的对象:
#define gco2u(o) check_exp((o)->tt == LUA_VUSERDATA, &((cast_u(o))->u))
最后返回的为下面Udata u这个数据:
Udata就是UserData在源码中的具体类型结构,我们下面就来详细学习一下:
本文地址:百科问答频道 https://www.neebe.cn/wenda/935433.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!