当前位置: 首页 > news >正文

Lua编程

文章目录

  • 概述
    • lua数据类型
    • 元表
      • 注意
    • 闭包
      • 表现
    • 实现
  • lua/c 接口编程
    • skynet中调用层次
    • 虚拟栈
    • C闭包
    • 注册表
    • userdata
    • lightuserdata
  • 小结

概述

这次是skynet,需要一些lua/c相关的。写一篇博客,记录下。希望有所收获。

lua数据类型

  • boolean , number , string , nil , function , table , userdata , lightuserdata , thread ;
    boolean 为 true 、 false ;其中 false 可以解决 table 作为 array 时,元素为 nil 时造成
    table 取长度未定义的行为;
  • number 为 integer 和 double 的总称;
  • string 常量字符串;这样 lua 中字符串比较只需要进行地址比较就行了;
  • nil 通常表示未定义或者不存在两种语义;
  • function 函数;与其他语言不同的是,lua 中 function 为第一类型;注意 lua 中的匿名函
    数,lua 文件可视为一个匿名函数;加载 lua 文件,可视为执行该匿名函数;
  • table 表;lua 中唯一的数据结构;既可以表示 hashtable 也可表示为 array;配合元表可以定制
    表复杂的功能(如实现面对对象编程中的类以及相应继承的功能);
  • userdata 完全用户数据;指向一块内存的指针,通过为 userdata 设置元表,lua 层可以使用
    该 userdata 提供的功能; userdata 为 lua 补充了数据结构,解决了 lua 数据结构单一的问
    题;可以在 c 中实现复杂的数据结构,生成库继而导出给 lua 使用;注意: userdata 指向的内存
    需要由 lua 创建,同时 userdata 的销毁也交由 lua gc 来自动回收;
  • lightuserdata 轻量用户数据;也是指向一块内存的指针,但是该内存由 c 创建,同时它的销毁
    也由 c 来完成;不能为它创建元表,轻量用户数据只有类型元表;通常用于 lua 想使用 c 的结构,但是不能让 lua 来释放的结构;在游戏客户端中用的比较多;
  • thread 线程;lua 中的协程和虚拟机都是 thread 类型;

元表

常用的有:

  • __index :索引 table[key] 。 当 table 不是表或是表 table 中不存在 key 这个键时,这个
    事件被触发。 此时,会读出 table 相应的元方法。
  • __newindex :索引赋值 table[key] = value 。 和索引事件类似,它发生在 table 不是表或
    是表 table 中不存在 key 这个键的时候。 此时,会读出 table 相应的元方法。
  • __gc :元表中用一个以字符串 " __gc " 为索引的域,那么就标记了这个对象需要触发终结器;

这些常用,是语言层次的,不区分客户端,服务器。

注意

  • 只有 table 和 userdata 对象有独自的元表,其他类型只有类型元表;
  • 只有 table 可以在 lua 中修改设置元表;
  • userdata 只能在 c 中修改设置元表,lua 中不能修改 userdata 元表;

闭包

表现

  • 函数内部可以访问函数外部的变量;
  • lua 文件是一个匿名函数;
    lua内部函数可以访问文件中函数体外的变量;

实现

  • C 函数以及绑定在 C 函数上的上值(upvalues);

lua/c 接口编程

skynet、openresty 都是深度使用 lua 语言的典范;学习 lua 不仅仅要学习基本用法,还要学会使
用 c 与 lua 交互,这样才学会了 lua 作为胶水语言的精髓;

skynet中调用层次

在这里插入图片描述

虚拟栈

  • 栈中只能存放 lua 类型的值,如果想用 c 的类型存储在栈中,需要将 c 类型转换为 lua 类型;
  • lua 调用 c 的函数都得到一个新的栈,独立于之前的栈;
  • c 调用 lua,每一个协程都有一个栈;
  • c 创建虚拟机时,伴随创建了一个主协程,默认创建一个虚拟栈;
  • 无论何时 Lua 调用 C , 它都只保证至少有 LUA_MINSTACK 这么多的堆栈空间可以使用。
    LUA_MINSTACK 一般被定义为 20 , 因此,只要你不是不断的把数据压栈, 通常你不用关心堆栈大小。

C闭包

  • 通过 lua_pushcclosure 用来创建 C 闭包;
  • 通过 lua_upvalueindex 伪索引来获取上值(lua 值);
  • 可以为多个导出函数(c 导出函数给 lua 使用)共享上值,这样可以少传递一个参数;

注册表

可以用来在多个 c 库中共享 lua 数据(包括 userdata 和 lightuserdata );

  • 一张预定义的表,用来保存任何 c 代码想保存的 lua 值;
  • 使用 LUA_REGISTRYINDEX 来索引;

userdata

  • userdata 是指向一块内存的指针,该内存由 lua 来创建,通过 void
    *lua_newuserdatauv(lua_State *L, size_t sz, int nuvalue) 这个函数来创建;注意:这
    块内存大小必须是固定的,不能动态增加,但是这块内存中的指针指向的数据可以动态增加;还有
    就是 userdata 可以绑定若干个 lua 值(又称uservalue)(在 lua 5.3 中只能绑定一个 lua 值,
    lua 5.4 可以绑定多个); userdata 与 uservalue 的关系是引用关系,也就是 uservalue 的生命周
    期与 userdata 的生命周期一致, userdata gc 时,uservalue 也会被释放;通常这个特性可以
    用来绑定一个 lua table 结构,因为 c 中没有 hash 结构,辅助 lua table 结构实现复杂的功
    能;也可以用来实现延迟 gc,如果某个 userdata 希望晚点 gc,在 userdata 的 __gc 元表中
    生成一个临时的 userdata ,然后将那个希望晚点 gc 的 userdata 绑定在这个临时 userdata
    的 uservalue 上;
  • int lua_getiuservalue (lua_State *L, int idx, int n) 来获取绑定在 userdata 上的
    uservalue;
  • int lua_setiuservalue (lua_State *L, int idx, int n) 来设置 userdata 上的
    uservalue;

lightuserdata

轻量用户数据也是指向一块内存的指针,但是该内存由 c 来创建和销毁;通常这块内存的生命周期
由 c 宿主语言来控制;可以将 lightuserdata 绑定在注册表中,让多个 lua 库共享该数据;在
skynet 中, lightuserdata 可以指向同一块数据,在多个 Actor 中传递这个 lightuserdata ,
然后分别为这个 lightuserdata 创建一个 userdata ; 在 userdata 中的 __gc 来释放这个
lightuserdata ;注意:为了避免这块内存多次释放,需要为这块内存加上引用计数;同时
skynet 中 actor 是多线程环境下运行,所以需要为该 lightuserdata 加上锁;这个锁必须是自
旋锁或者原子操作,因为 actor 调度是自旋锁,必须使用比它更小的粒度的锁;如果
lightuserdata 操作粒度过大,应该改成只在一个 actor 中加载,其他 actor 通过消息来共享数
据;

小结

这一篇lua编程不同于之前的lua源码阅读,写那一篇的时候,主要是在写一些源码中的内容;这一篇,包括各种数据结构,c,以及lua的。感兴趣,都可以看看,也可以一起学习学习。OK,这篇结束。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • LinuxCentos中安装apache网站服务详细教程
  • Vue中!.和?.是什么意思
  • Thinkphp仿华为商城源码/红色风格电脑手机数码商城系统网站源码
  • C++要点总结_02_表达式与语句
  • mongodb数据库运维之创建数据库及赋权限
  • 【解决方案】华普微汽车智能钥匙解决方案
  • 【2024蓝桥杯/C++/B组/传送阵】
  • 小程序开发_05
  • Vue 3 中使用 InMap 绘制热力图
  • kubernetes管理GUI工具Lens
  • 嵌入式软件工程师面试:RTOS相关问题全攻略
  • vue路由跳转时改变路由参数组件不渲染问题【已解决】
  • opencascade AIS_MouseGesture AIS_MultipleConnectedInteractive源码学习
  • 回溯---组合
  • Postman中的灾难恢复演练:API的弹性测试策略
  • 【Leetcode】101. 对称二叉树
  • 分享的文章《人生如棋》
  • 【Amaple教程】5. 插件
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • AngularJS指令开发(1)——参数详解
  • Docker: 容器互访的三种方式
  • ES学习笔记(12)--Symbol
  • JavaScript学习总结——原型
  • jdbc就是这么简单
  • magento 货币换算
  • mysql_config not found
  • SegmentFault 2015 Top Rank
  • tensorflow学习笔记3——MNIST应用篇
  • tweak 支持第三方库
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 前端之React实战:创建跨平台的项目架构
  • 人脸识别最新开发经验demo
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 异常机制详解
  • 用quicker-worker.js轻松跑一个大数据遍历
  • ​​​【收录 Hello 算法】10.4 哈希优化策略
  • #NOIP 2014#Day.2 T3 解方程
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (2.2w字)前端单元测试之Jest详解篇
  • (7)svelte 教程: Props(属性)
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (pojstep1.3.1)1017(构造法模拟)
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一) springboot详细介绍
  • ***通过什么方式***网吧
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .form文件_SSM框架文件上传篇
  • .Net CF下精确的计时器
  • .net mvc 获取url中controller和action
  • .NET 分布式技术比较