userdata说明:

0、Lua中使用userdata类型来表示在C中定义的类型。userdata只是提供了一块原始的内存区域,可以用来存储任何东西,并且,在lua中userdata没有任何预定义的操作。在C中调用函数lua_newuserdata会根据指定的大小分配一块内存,并将相应的userdata压入栈中,最后返回这个内存块的地址:void *lua_newuserdata(lua_State*L,size_t size)。

1、实质在C中定义lua的userdata,与定义C模块完全类似,只不过通常这时需要通过调用lua_newuserdata来告诉lua分配一块额外的内存,而在内存所有相关的操作都是在C中的定义的,实质就是C模块中的接口。注意这块分配的额外内存是由Lua垃圾收集器来管理的,无须关心起释放等情况。

2、在实现一个Lua的程序库或userdate,必须保证该库或userdata的接口不应破坏C数据或在Lua中导致core dump。

3、可以为每种userdata创建一个唯一的元表,来辨别不同类型的userdata,每当创建了一个userdata后,就用相应的元表来标记它,而每得到一个userdata后,就检查它是否拥有正确的元表,注意Lua代码中不能改变userdata的元表(当能增加已有元表的属性,比如对元表key为__index赋值)。通常是将这个元表存储在注册表中,也类型名作为key,元表为value。辅助库提供了一些函数来实现这些:

int luaL_newmetatable(lua_State*L, const char *tname);

void luaL_getmetatable(lua_State *L,const char *tnaem);

void *luaL_checkudata(lua_State*L,int index,const char *tname);

4、轻量级userdata是一种表示C指针的值(即void*),要将一个轻量级userdata放入栈中,只需要调用lua_pushlightuserdata即可。轻量级userdata只是一个指针而已。它没有元表,就像数字一样,轻量级userdata无须受垃圾收集器的管理。

5、Lua在释放完全userdata所关联的内存时,若发现userdata对应的元表还有__gc元方法,则会调用这个方法,并以userdata自身作为参数传入。利用该特性,可以再回收userdata的同时,释放与此userdata相关联的资源。

full userdata

static struct StudentTag

{

char *strName; // 学生姓名

char *strNum; // 学号

int iSex; // 学生性别

int iAge; // 学生年龄

};

//lua 中通过调用这个接口来得到 pStudent指针

static int Student(lua_State *L)

{

size_t iBytes = sizeof(struct StudentTag);

struct StudentTag *pStudent;

pStudent = (struct StudentTag *)lua_newuserdata(L, iBytes);

return 1; // 新的userdata已经在栈上了

}

static int GetName(lua_State *L)

{

struct StudentTag *pStudent = (struct StudentTag *)lua_touserdata(L, 1);

luaL_argcheck(L, pStudent != NULL, 1, "Wrong Parameter");

lua_pushstring(L, pStudent->strName);

return 1;

}

static int SetName(lua_State *L)

{

// 第一个参数是userdata

struct StudentTag *pStudent = (struct StudentTag *)lua_touserdata(L, 1);

luaL_argcheck(L, pStudent != NULL, 1, "Wrong Parameter");

// 第二个参数是一个字符串

const char *pName = luaL_checkstring(L, 2);//检查第2个参数是不是string,并返回参数值

luaL_argcheck(L, pName != NULL && pName != "", 2, "Wrong Parameter");

pStudent->strName = (char *)pName;

return 0;

}

static int GetAge(lua_State *L)

{

struct StudentTag *pStudent = (struct StudentTag *)lua_touserdata(L, 1);

luaL_argcheck(L, pStudent != NULL, 1, "Wrong Parameter");

lua_pushinteger(L, pStudent->iAge);

return 1;

}

static int SetAge(lua_State *L)

{

struct StudentTag *pStudent = (struct StudentTag *)lua_touserdata(L, 1);

luaL_argcheck(L, pStudent != NULL, 1, "Wrong Parameter");

int iAge = luaL_checkinteger(L, 2);

luaL_argcheck(L, iAge >= 6 && iAge <= 100, 2, "Wrong Parameter");

pStudent->iAge = iAge;

return 0;

}

static int GetSex(lua_State *L)

{

// 这里由你来补充

struct StudentTag *pStudent = (struct StudentTag *)lua_touserdata(L, 1);

luaL_argcheck(L, pStudent != NULL, 1, "get wrong arg from lua");

lua_pushnumber(L, pStudent->iSex);//通过C++操作把数据放入到堆栈中,  1表示男 2表示女

return 1;

}

static int SetSex(lua_State *L)

{

// 这里由你来补充

struct StudentTag *pStudent = (struct StudentTag *)lua_touserdata(L, 1);

luaL_argcheck(L, pStudent != NULL, 1, "get wrong arg from lua");

int iSex = luaL_checkinteger(L, 2);

luaL_argcheck(L, iSex == 1 || iSex == 2, 2, "get wrong arg from lua");

pStudent->iSex = iSex;

return 0;

}

static int GetNum(lua_State *L)

{

// 这里由你来补充

return 1;

}

static int SetNum(lua_State *L)

{

// 这里由你来补充

return 0;

}

static struct luaL_reg arrayFunc[] =

{

{"new", Student},//注册成为Student的接口

{"getName", GetName},

{"setName", SetName},

{"getAge", GetAge},

{"setAge", SetAge},

{"getSex", GetSex},

{"setSex", SetSex},

{"getNum", GetNum},

{"setNum", SetNum},

{NULL, NULL}

};

int luaopen_userdatademo1(lua_State *L)

{

luaL_register(L, "Student", arrayFunc);

luaL_dofile(L, "main.lua");

return 1;

}

.lua文件代码:

local objStudent = Student.new()

Student.setName(objStudent, "果冻想")

Student.setAge(objStudent, 15)

Student.setSex(objStudent, 2)

local strName = Student.getName(objStudent)

local iAge = Student.getAge(objStudent)

local iSex = Student.getSex(objStudent)

print("1")

print(strName)

print(iAge)

print("2")

print("iSex" .. iSex)

轻量级userdata

轻量级userdata是一种表示C指针的值(即void *)。由于它是一个值,所以不用创建它。要将一个轻量级userdata放入栈中,只需要调用lua_pushlightuserdata即可。

void lua_pushlightuserdata(lua_State *L,void *p);

尽管两种userdata在名称上差不多,但它们之间还是存在很大不同的。轻量级userdata不是缓冲,只是一个指针而已。它也没有元表,就像数字一样,轻量级userdata不受到垃圾收集器的管理。

轻量级userdata的真正用途是相等性判断。一个完全userdata是一个对象,它只与自身相等。而一个轻量级userdata则表示了一个C指针的值。因此,它与所有表示同一个指针的轻量级userdata相等。可以将轻量级userdata用于查找Lua中的C对象。

// 压入轻量级userdata,一个static变量的地址

static char key = 'k';

lua_pushlightuserdata(L, (void *)&key);

lua_pushstring(L, "JellyThink");

lua_settable(L, LUA_REGISTRYINDEX);

由于静态变量的地址在一个进程中具有唯一性,所以绝对不会出现重复key的问题。

// 从注册表中取对应的值

lua_pushlightuserdata(L, (void *)&key);

lua_gettable(L,  LUA_REGISTRYINDEX);

C++中代码:

lua_State *L = luaL_newstate();

if (L)

{

luaL_openlibs(L);

}

lua_pushnumber(L, 20);

lua_setglobal(L, "dde");

static char key = 'k';

lua_pushlightuserdata(L, (void *)&key);

lua_setglobal(L, "ddee");

luaL_dofile(L, "tabletest.lua");

.lua代码

print("sdfe" .. dde)

print("type" .. type(ddee))

结果:

————————————————
版权声明:本文为CSDN博主「从小就爱吃肉」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dugaoda/article/details/50259497

lua——userdata使用相关推荐

  1. lua userdata

    2019独角兽企业重金招聘Python工程师标准>>> userdata类型是为了方便C/C++对Lua进行扩展,因为在用C/C++扩展时,我们经常会自定义数据类型,如: typed ...

  2. Lua Userdata 的元表 (Metatable)

    在Lua C API编程上,经常有一些博客会说,必须使用luaL_newmetatable和luaL_setmetatable来给userdata加元表.还说给userdata加的元表不是普通的tab ...

  3. Lua userdata详解

    原文连接:https://blog.csdn.net/u012787710/article/details/52495011. userdata (Lua5.3) Q:什么是 userdata ? A ...

  4. lua userdata 汇总

    lua_newuserdata简单使用  (http://blog.csdn.net/slionls/article/details/23358795) userdata (http://www.sh ...

  5. Lua userdata和lightuserdata

    userdata和lightuserdata 可以让C返回一个句柄给Lua,而Lua可以将句柄再通过在C中注册的方法传回C userdata: userdata通过Lua的API(lua_newuse ...

  6. lua与c#交互篇 | 合理用好lua+unity,更省性能的方案整理

    前言 在看了uwa之前发布的<Unity项目常见Lua解决方案性能比较>,决定动手写一篇关于lua+unity方案的性能优化文. 整合lua是目前最强大的unity热更新方案,毕竟这是唯一 ...

  7. Lua快速入门篇(XLua教程)(Yanlz+热更新+xLua+配置+热补丁+第三方库+API+二次开发+常见问题+示例参考)

                            <Lua热更新> ##<Lua热更新>发布说明: ++++"Lua热更新"开始了,立钻哥哥终于开始此部分的探 ...

  8. 如何销毁一个实例化对象_基于脚本的游戏对象系统(1) 实例化、组件及生命周期...

    前置说明:这是2016年在开发 CreateX Engine 2 时写的文章,这个专栏也开了两年,一直空着,最近有时间慢慢填写内容,两年多过去了,对于引擎的理念也有了一些变化,可能会不一致,甚至是颠覆 ...

  9. unity性能优化方案整理 一些思路 一些技巧(持续更新 2019-09-12)

    原文链接1:https://www.cnblogs.com/zhenlong/p/4862869.html 原文链接2:http://www.xuanyusong.com/archives/3205 ...

最新文章

  1. redis集合数据过期_如何从Redis中的集合中自动删除过期的密钥?
  2. 数据库知识点补充::约束
  3. 分布式系统的Raft算法——在失联阶段这个老Leader的任何更新都不能算commit,都回滚,接受新的Leader的新的更新 意味着还是可能丢数据!!!...
  4. 【转】修改版WinXP集体歇业避免遭遇调查
  5. java.两个例子充分阐述多态的可拓展性
  6. Velocity语法大全
  7. LeetCode 36有效的数独37解数独(八皇后问题)
  8. php layui实现添加input,Layui实现input输入和选择的方法
  9. python elasticsearch update_使用python的elasticsearch部分更新
  10. PowerDesigner-快速入门(极简教程)
  11. Python中的运算符是什么?本文详解!
  12. PHP怎么使用ckeditor集成,php调用ckeditor?怎么调用ckeditor
  13. STM32:堆和栈(Heap Stack)及SRAM存储使用
  14. python计算机入门_Python零基础入门(1)-------计算机基础
  15. proteus三输入与非门名字_dnf冒险团名字怎么改?冒险团名称修改方法
  16. 指纹考勤机使用的基本操作方法
  17. 【初识 JQMobile 小小总结】
  18. E430 加装固态硬盘(SSD)参考
  19. UE4 InputMode无法锁定编辑器视口鼠标解决方案
  20. Squirrel中的类与实例

热门文章

  1. ios wkwebview弹框_iOS WKWebView的使用
  2. 单车行业协会官方公布全球十大顶级奢侈自行车品牌排行榜
  3. 深入理解nandflash基本特性
  4. Tomcat的服务器介绍
  5. MySQL 动态标签
  6. Java递归遍历文件夹
  7. 2019 vs 安装odt_北京市2019二级造价师考试教材出版信息,免费送考试大纲
  8. 弹出菜单PopupMenu
  9. 计算机桌面联机,如何设置电脑联机共享(详细图解)
  10. Linux下raise函数,信号发送函数kill()和raise()