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

Lua基础

table

基本原理:
table是一种特殊的容器,可以向数组一样按照索引存取,也能按照键值对存取。

local mytable = {1,2,3} --相当于数组
local mytable = {[1]=1,[2]=2,[3]=3} --和上面等价
local mytable = {1,2,3,[3] = 4} --隐式赋值会覆盖掉显式赋值
local mytable = {1,2,5,a=9,b="bo"} --支持索引存储,也支持键值对存储
print(mytable[4])--输出为nil,键值对存储不能用索引访问
print(mytable.a) --正确访问方式
mytable.id = "1001" --不用事先定义,使用的时候直接赋值,类似python
--我们收数据的时候只用收table一种数据类型就可以了,约定好里面有什么数据后直接取即可
mytable.userdata = {atk = 15, def = 20} --table可以存放很多数据类型,并且可以嵌套
function mytable:test(p)print(p)print(mytable[1])
endfor i,v in  pairs(mytable) do  --遍历方式,输出的是索引和内容,或者键值对,忽略nil项print(i)print(v)
end
for i,v in ipairs(mytable) do  --遍历方式,输出的是索引和内容,并且不能遍历键值对,并且遍历索引时遇到nil会停止输出print(i)print(v)
end
if next(mytable) == nil then --next第二个参数是索引位,判断索引位的下一位,如果为空就判断第一位print("为空")
endprint(#mytable)  --判断table长度,但注意table里面不能有nil,否则长度计算会在遇到nil的地方停止

底层实现:
table:底层实现分数组部分和哈希表部分。数组部分,从 1 开始做整数数字索引,这可以提供紧凑且高效的随机访问;数组部分存储在 TValue *array 中,其长度 信息存储在 int sizearray 中。哈希表存储在 Node *node,哈希表的大小用 lu_byte lsizenode 表示,lsizenode 表示的是 2 的几次幂,而不是实际大小,因 为哈希表的大小一定是 2 的整数次幂。哈希冲突后,采取开放地址法,应对 hash碰撞。每个 Table 结构,最多会由三块连续内存构成:
(1) 一个 table 结构
(2) 一块存放了连续整数索引的数组
(3) 一块大小为 2 的整数次幂的哈希表

string底层

Lua 中的字符串(string)底层实现使用了一种叫作"短字符串优化"(Short String Optimization)的策略。该策略基于以下两种情况来存储字符串:

短字符串:长度小于等于 40 字节的字符串会直接存储在 Lua 内部的字符串对象中,而不需要额外的内存分配。这种情况下,字符串的数据会被直接存储在字符串对象的数据字段中。

长字符串:长度超过 40 字节的字符串则会分配额外的内存空间来存储字符串数据。Lua 使用一个单独的内存块来存储长字符串的数据,并在字符串对象中存储指向该内存块的指针。

无论是短字符串还是长字符串,Lua 的字符串都是不可变的(immutable)。这意味着一旦创建了一个字符串,就不能再修改它的内容。如果需要对字符串进行修改,必须创建一个新的字符串。

Lua 的字符串实现具有一些优点和注意事项:

  • 节约内存:短字符串直接存储在字符串对象中,无需额外的内存分配,节约了内存空间。长字符串使用单独的内存块存储,可以避免字符串占用过多的 Lua 内存。

  • 高效性能:由于字符串不可变,可以在多个 Lua 值之间共享相同的字符串对象,避免了重复的字符串复制操作,提高了性能。

  • 注意拼接操作:由于字符串不可变,每次对字符串进行拼接操作都会创建一个新的字符串对象。如果需要频繁进行字符串拼接操作,可能会导致大量的内存分配和对象创建,影响性能。在这种情况下,可以使用 Lua 中的字符串缓冲区(如 table.concat 函数)或者考虑使用 LuaJIT 提供的 FFI 接口来进行高效的字符串拼接。

元表

local mytable = {1,2,3}
local mymetatable = {__index = {b=6,c="c"}  
}
mytable = setmetatable(mytable, mymetatable)  --元表扩展了普通表的功能
getmetatable(mytable)  --获取元表
print(mytable.c)  --table里面没有的话会查找元表中的index来调用local mymetatable = {__index = function(table,key)   --访问table中没有的元素调用元表中的indexif key == "b" thenreturn "hello"elsereturn nilendend  --如果index是一个方法__newindex = function(table,key)    --给table和元表中没有的数组元素赋值或给一个变量赋值会执行newindexprint("被调用")return "NoValue"end__call = function(mytable, newtable)  --把元表当做方法(函数)使用的时候调用callsum = 0for i = 1, #mytable do sum = sum + mytable[i]endfor i = 1, #newtable do sum = sum + newtable[i]endreturn sumend__tostring = function(mytable)     --想要直接输出这个表的时候调用return #mytableend__add = function(mytable, newtable)  --两个表进行相加操作的时候调用for i = 1, table.maxn(newtable) dotable.insert(mytable, table.maxn(mytable)+1,newtable[i])endreturn mytableend}
mytable = setmetatable({1,2,3}, mymetatable)
function mytable:test(p)print(p)
end
print(mytable.b)  --会调用index里面的方法输出hello
mytable.c = 10    --设置没有定义的变量会触发__newindex,一般里面做一些报错提醒
mytable[1] = 6    --已经存在的数组元素,不会触发__newindex
mytable[5] = 666  --不存在的数组元素,会触发__newindex
newtable = {10,20,30}
print(mytable(newtable))  --调用__call
print(mytable)       --调用__tostring
mytable = mytable + newtable
print(mytable)---查找和赋值不调用index和newindex函数的方法
print(rawget(mytable ,mytable.w))  --输出的是nil
rawset(mytable,"w",1)   --设置不存在的变量不会调用newIndexmytable:test(5)           --这两种调用方式等价,冒号是一个语法糖
mytable.test(mytable,5)

模块

一个文件想要用另外一个文件的变量,就要用到require。但是如果我们不想每次使用都require,我们可以把lua文件定义成module,这样只需要require一次加载进来,就能在所有文件中访问这个文件的变量。
普通用法

require("math_func")
local ret = math_abs(-7)
print(ret)

定义Module的方式:

module("device",package.seeall)function get_device_name()return "guest9527:
end
local name = device.get_device.name()

接口

如果我们不想把一个lua文件中的所有变量都暴露出去,我们可以在文件中定义一个table作为接口,把所有变量设为local,把想要暴露的添加到table中,然后返回即可。

function math_abs(value)if(value < 0) thenreturn -valueendreturn valueend
function math_vec_length_2(vec)return vec.x * vec.x + vec.y - vec.y
end
function _test_func(...)print("test")
end
local list = {abs = math_abs,lenth = math_vec_length_2,test_func = _test_func,
}return list

lua的数据类型

table
function
nil
boolean
number:包括整数,浮点数等
string

userdata:userdata类型主要用来表示在C/C++中定义的类型,即用来实现扩展lua,这些扩展代码通常是用C/C++来实现的。对lua 虚拟机来说userdata只是提供了一块原始的内存区域,可以用来存储任何东西,并且在lua中userdata没有任何预定义的操作。注意这块分配的额外内存是由Lua垃圾收集器来管理的,无须关心起释放等情况。
thread:线程
注意:数据类型不是固定了,一个数据赋值了整型之后,也可以赋值字符串。
注意:函数也是变量的一种,可以随意赋值给变量
注意:字符串之间的拼接用…

local a = 5
print(type(a))  --打印类型
foo2 =function foo(x)  --函数的赋值print(x)end
foo2(x)

点和冒号的区别

冒号隐式地传递了一个调用这个函数的表的示例进去,可以省略一个参数。

local a = {}
--下面两个函数等同
function a.test(self,a,b)  --这里self必须传进去本身才行print("atest",self)
end
function a:test(a,b)print("atest",self)  --冒号包含了self机制
end

两者不能混着用,如果定义的是冒号,用的时候是点,就会导致找不到self而报错。

闭包

语法域:函数可以嵌套在另一个函数中,内部函数可访问外部函数的局部变量,这样可以用来实现面向对象的编程
闭包:lua编译一个函数的时候,会生成一个原型prototype,包含了函数体对应的虚拟机指令,函数体中的常量,调试信息。运行的到函数的时候会创建一个新的数据对象,对象中包含了响应函数原型的引用和一个数组,包含了所有upvalue的引用(传进来的值),这个数据对象称为闭包。
注意:lua支持函数有多返回值

function f1(n)local fuction f2()print(n)endreturn f2
endg1 = f1(2021)
g1()
g2 = f1(2022)
g2()function create(n)local function foo()local function foo1()print(n)endlocal function foo2()n = n + 10endreturn foo1,foo2endreturn foo
end
f0 = create(2021)
f1,f2 = f0()
g1,g2 = f0()
f1()
f2()
g1()
g2()
f1()--闭包可以作为高阶函数的参数
table.sort(t,function(t1,t2) return t1.param > t2.param end)
--重写(类似面向对象),可以用来添加验证
local oldOpen = io.open
local accessOk = function(filename,mode)--方法体end
io.open = function(filename,mode)if accessOk(filename,mode) thenreturn oldOpen(file,mode)elsereturn nil,"校验失败"endend--实现迭代器
function values(t)local i = 0return function() i=i+1 return t[i] endend
t = {1,2,3,4,5,6}
iter = values(t)
print(iter())
print(iter())
print(iter())

C#和lua的相互调用

c语言可以和lua直接通信,lua就是c语言开发的,C#要和lua通信,需要先调用C语言,C语言再调用lua,Xlua插件封装了C#调用C语言的接口。
C 调用 Lua 实际上是:由 C 先把数据放入栈中,由 Lua 去栈中取数据,然后返回数据对应的值到栈顶,再由栈顶返回 C。
Lua 调 C 也一样:先编写自己的 C 模块,然后注册函数到 Lua 解释器中,然后由Lua 去调用这个模块的函数。
Lua虚拟栈:从底往上是1到n,从顶往下时-1到-n,lua里面用到的数据类型都可以入栈

Lua实现只读表

local readOnly
readOnly = function(t)for k,v in pairs(t) doif type(v) == "table" thent[k] = readOnly(v)endendlocal nt = {}local mt = {__index = t,__newindex = function(t,key,value)error("this is a readonly table")end}setmetatable(nt,mt)return nt
endlocal a = {x=1,y=2}
a = readOnly(a)
a.x = 3 --错误

当我们对readOnly的table进行赋值会调用newIndex函数,从而抛出错误

Lua GC

从Lua 5.1开始,采用三色增量标记清除算法。好处:它不必再要求GC一次性扫描所有的对象,这个GC过程可以是增量的,可以被中断再恢复并继续进行的。3种颜色分类如下:

白色:当前对象为待访问状态,表示对象还没有被GC标记过,这也是任何一个对象创建后的初始状态。换言之,如果一个对象在结束GC扫描过程后仍然是白色,则说明该对象没有被系统中的任何一个对象所引用,可以回收其空间了。

灰色:当前对象为待扫描状态,表示对象已经被GC访问过,但是该对象引用的其他对象还没有被访问到。

黑色:当前对象为已扫描状态,表示对象已经被GC访问过,并且该对象引用的其他对象也被访问过了。当GC完后被重置为白色。
伪代码:

每个新创建的对象颜色为白色//初始化阶段
遍历root节点中引用的对象,从白色置为灰色,并且放入到灰色节点列表中//标记阶段
当灰色链表中还有未扫描的元素:从中取出一个对象并将其标记为黑色遍历这个对象关联的其他所有对象:如果是白色:标记为灰色,加入灰色链表中//回收阶段
遍历所有对象:如果为白色:这些对象都是没有被引用的对象,逐个回收否则:重新加入对象链表中等待下一轮的GC检查

相关文章:

Lua基础

table 基本原理&#xff1a; table是一种特殊的容器&#xff0c;可以向数组一样按照索引存取&#xff0c;也能按照键值对存取。 local mytable {1,2,3} --相当于数组 local mytable {[1]1,[2]2,[3]3} --和上面等价 local mytable {1,2,3,[3] 4} --隐式赋值会覆盖掉显式赋…...

微信小程序之开发工具介绍

一、微信小程序开发工具下载 微信小程序开发工具下载可以参考这篇博客《微信小程序开发者工具下载-CSDN博客》 二、开发工具组成部分 如下图所示&#xff0c;开发者工具主要由菜单栏、工具栏、模拟器、编辑器和调试器 5 个部分组成。。 1、菜单栏 菜单栏中主要包括项目、文…...

【AUTOSAR】【以太网】DoIp

AUTOSAR专栏——总目录_嵌入式知行合一的博客-CSDN博客文章浏览阅读217次。本文主要汇总该专栏文章,以方便各位读者阅读。https://xianfan.blog.csdn.net/article/details/132072415 目录 一、概述 二、功能描述 2.1 Do...

游戏中UI的性能优化手段

UI方面有许多性能优化的技术或手段&#xff0c;以下是其中一些常见的例子&#xff1a; 惰性加载&#xff1a;对于长列表、大图等需要加载大量数据和资源的组件&#xff0c;可以采用惰性加载的方式&#xff0c;即在用户需要时再进行加载。这样可以减少初始加载时间和内存占用&am…...

Idea快速生成测试类

例如写写完一个功能类,需要对里面方法进行测试 在当前页面 按住CTRLSHFITT 选择你要生成的测试方法 点击OK,就会在test目录下在你对应包下生成对应测试类...

Java文件操作详解

CONTENTS 1. 文件和目录路径1.1 获取Path的片段1.2 获取Path信息1.3 添加或删除路径片段 2. 文件系统3. 查找文件4. 读写文件 1. 文件和目录路径 Path 对象代表的是一个文件或目录的路径&#xff0c;它是在不同的操作系统和文件系统之上的抽象。它的目的是&#xff0c;在构建路…...

二叉树系列主题Code

Python实现二叉树遍历 # 定义二叉树节点类 class TreeNode: def __init__(self, val0, leftNone, rightNone): self.val val self.left left self.right right # 前序遍历&#xff08;非递归&#xff09; def preorderTraversal(root): if not root: return [] …...

Leetcode 673. 最长递增子序列的个数 C++

673最长递增子序列的个数 给定一个未排序的整数数组 nums &#xff0c; 返回最长递增子序列的个数 。 注意 这个数列必须是 严格 递增的。 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递增子序列&#xff0c;分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。 示例 2: 输入: …...

html用css grid实现自适应四宫格放视频

想同时播放四个本地视频&#xff1a; 四宫格&#xff1b;自式应&#xff0c;即放缩浏览器时&#xff0c;四宫格也跟着放缩&#xff1b;尽量填满页面&#xff08;F11 浏览器全屏时可以填满整个屏幕&#xff09;。 在 html 中放视频用 video 标签&#xff0c;参考 [1]&#xff1…...

【机器学习可解释性】5.SHAP值的高级使用

机器学习可解释性 1.模型洞察的价值2.特征重要性排列3.部分依赖图4.SHAP 值5.SHAP值的高级使用 正文 汇总SHAP值以获得更详细的模型解释 总体回顾 我们从学习排列重要性和部分依赖图开始&#xff0c;以显示学习后的模型的内容。 然后我们学习了SHAP值来分解单个预测的组成部…...

CentOS开机自动运行jar程序实现

前面已经有一篇文章介绍jar包如何在CentOS上运行&#xff0c;《在linux上运行jar程序操作记录》 后来发现系统重启后不能自动运行&#xff0c;导致每次都要手动打开&#xff0c;这篇介绍如何自动开机启动运行jar程序。 一、找到JDK程序执行位置 [rootlocalhost /]# which jav…...

matlab双目标定中基线物理长度获取

在MATLAB进行双目摄像机标定时,通常会获得相机的内参,其中包括像素单位的焦距(focal length)以及物理单位的基线长度(baseline)。对于应用中的深度估计和测量,基线长度的物理单位非常重要,因为它直接影响到深度信息的准确性。有时候,您可能只能获取像素单位的焦距和棋…...

自己动手实现一个深度学习算法——二、神经网络的实现

文章目录 1. 神经网络概述1&#xff09;表示2&#xff09;激活函数3&#xff09;sigmoid函数4&#xff09;阶跃函数的实现5&#xff09;sigmoid函数的实现6)sigmoid函数和阶跃函数的比较7&#xff09;非线性函数8&#xff09;ReLU函数 2.三层神经网络的实现1&#xff09;结构2&…...

gRPC源码剖析-Builder模式

一、Builder模式 1、定义 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的的表示。 2、适用场景 当创建复杂对象的算法应独立于该对象的组成部分以及它们的装配方式时。 当构造过程必须允许被构造的对象有不同的表示时。 说人话&#xff1a…...

ARM传输数据以及移位操作

3.2.2 数据传送指令 LDR/STR指令用来在寄存器和内存之间输送数据。如果我们想要在寄存器之间传送数据&#xff0c;则可以使用MOV指令。MOV指令的格式如下。 MOV {cond} {s}Rd, oprand2 MOV {cond} {s}Rd, oprand2 其中&#xff0c;{cond}为条件指令可选项&#xff0c;{s}用来表…...

06、如何将对象数组里 obj 的 key 值变成动态的(即:每一个对象对应的 key 值都不同)

1、数据情况&#xff1a; 其一、从后端拿到的数据为&#xff1a; let arr [1,3,6,10,11,23,24] 其二、目标数据为&#xff1a; [{vlan_1: 1, value: 1}, {vlan_3: 3, value: 1}, {vlan_6: 6, value: 1}, {vlan_10: 10, value: 1}, {vlan_11: 11, value: 1}, {vlan_23: 23, v…...

ngx_http_request_s

/* 罗剑锋老师的注释参考&#xff1a; https://github.com/chronolaw/annotated_nginx/blob/master/nginx/src/http/ngx_http_request.h */struct ngx_http_request_s {uint32_t signature; /* "HTTP" */ngx_connection_t …...

Docker 学习路线 2:底层技术

了解驱动Docker的核心技术将让您更深入地了解Docker的工作原理&#xff0c;并有助于您更有效地使用该平台。 Linux容器&#xff08;LXC&#xff09; Linux容器&#xff08;LXC&#xff09;是Docker的基础。 LXC是一种轻量级的虚拟化解决方案&#xff0c;允许多个隔离的Linux系…...

UEFI实战——显示图片

一、准备工作 1.1 BMP格式图片 参考:BMP格式详解获取“BMP格式详解”文档里的图片,命名为Logo.bmp将Logo.bmp图片放到U盘里,U盘格式FAT32二、实例代码 2.1 代码结构 TextPkg/ ├── Display.c ├── GetFile.c ├── Test.c ├── Test.dsc ├── Test.h └── Tes…...

Ansible中的playbook

目录 一、playbook简介 二、playbook的语法 三、playbook的核心组件 四、playbook的执行命令 五、vim 设定技巧 六、基本示例 一、playbook简介 1、playbook与ad-hoc相比&#xff0c;是一种完全不同的运用。 2、playbook是一种简单的配置管理系统与多机器部署系统的基础…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

【AI News | 20250609】每日AI进展

AI Repos 1、OpenHands-Versa OpenHands-Versa 是一个通用型 AI 智能体&#xff0c;通过结合代码编辑与执行、网络搜索、多模态网络浏览和文件访问等通用工具&#xff0c;在软件工程、网络导航和工作流自动化等多个领域展现出卓越性能。它在 SWE-Bench Multimodal、GAIA 和 Th…...