lua随便写点

  nil是一个类型也只有一个nil值
  除了false和nil,其他数值参与运算,都视为ture,包括0
  and:第一个值为false,返回false,否则返回第二个操作数
  or:第一个值不为false,返回第一个操作数,否则返回第二个操作数
    x = x or y:x无值时将x赋值为y
  not:永远返回真假值而不返回操作数

数值类型

  分为整形和浮点,
    type(3) 和 type(3.0)的类型都是number,他们之间可以相互转化,而且3 == 3.0为ture
    区分类型可以用math.type()
    要么区分每一个数值的类型,要么就无视类型

  整形 / 整形也不会截断,自然而然转换成浮点,如果想要截断,用 整形 // 整形3//2
  取整函数:math.floor(),math.ceil(),math.modf(),分别是向负无穷、正无穷、0取整

  转型:
    整数 + 0.0   转为浮点型
    浮点 | 0    转为整形,如果转整形的时候小数不为0,那么就产生了截断,会抛出异常,也就是说3.111不能这样转
    转整形或者失败保持原来的值:return math.tointeger(x) or x

字符串

  字符串参与算术运算默认视为浮点
  字符串声明:单引号双引号都可
  字符串长度:a = “test”; print(#a)
  字符串连接:
    ”test1“ . . ”test“
    输出:test1test2
    如果是10 .. 20,需要在..前面加空格,不然视为浮点
  多行字符串:

	str = 
	[[
		字符串内容
	]]
	
	如果字符串中间有table[table[2]]的情况,可以加任意多个=来区分头尾,等号数量相等才会匹配
	
	str = 
	[===[
		字符串内容;
		table[table[2]];
	]===]	

  字符串相关函数:
    tonumber(字符串,2-36进制)
    tostring(数值)
    string.len(str) 和#取长度等价
    string.rep(str,count) 把字符串重复写几次
    string.reverse(str) 反转
    string.lower(str)
    string.upper(str)
    string.sub(str, strat, end) 取子串,含首尾,索引从1开始,-1代表反向第一个
    inta, intb = string.find(str, substr) 返回start和end
    string.format(“%d %x %f %s”, parm4,parm4,parm4,parm4,)分别是十进制、十六进制、浮点、字符串

表类型

  表的创建、初始化:
    a = {}
    数组形式的表:{"11", 12, "13",} 等价于 { [1] = "11", [2] = 12, [3] = "13",}
    哈希形式的表:{x = 0, y = 0,} 等价于 { ["x"] = 0, ["y"] = 0,}
    两种可以混起来使用

  表是一个对象,初始化时赋值给某个变量,引用+1,引用为0时对象释放
  变量赋值nil引用-1
  当给某个键赋值nil,表示删除
  下文使用的对象:test_table = {["a"] = "11", ["b"] = 12, ["c"] = "13"}

  test_table.a等价于test_table["a"],就像math.sin那样,是math.[“sin”],只不过这个键里是一个函数
  如果一个浮点数作为索引,并且这个浮点数可以无损转为整数,那他就是整数索引,否则还是保持浮点数索引
  #test_table井号也是可以取到表长度的,但是nil的不计入内

  关于 嵌套过深的表 的 安全访问:
    E = {};
    val = (((test.table or E).one_floor or E).two_floor or E).three_floor

  表相关的库函数:
    table.insert(表对象, 插入个什么值到尾部)
    table.insert(表对象, 索引位置, 插入个什么值)
    table.remove(表对象删最后一个元素)
    table.remove(表对象, 删哪个位置)
    table.move(表对象, src_start, src_end, 目标索引) 一个区间移动到某个位置,原来位置的自动向前挪或者向后挪

  遍历:
    以下两种遍历区别在于:
    pairs是无序的,每次都可能顺序不一样
    ipairs是有序的,但是只能用于那种索引是1、2、3这样的,而且中间不能缺失,否则就会有问题
    for k, v in pairs(test_table) do   |  for k, v in ipairs(test_table) do
      pirnt(k, v)
    end

函数

  函数声明:
    function Fun_name(参数列表)
      xxxxxxxxxxxxxxxxxxx
      return x1,x2,x3    // 可选的多值返回语句
    end

  lua的参数大多数是时候都是值传递,只有参数是一个表的时候,其行为像引用传递
  调用函数时,参数比函数定义多则丢弃,少则视为nil

  对于多返回值的函数调用:
    若有function Fun_1 return "Luo1", "Luo2" end
    如果左边没有=来接受返回值,那么所有返回值被丢弃
    如果左边a, b, c = Fun_1(),那么c的值为nil

    只有函数第一个返回值有效的情况:
      a = Fun_1(),那么第二个及之后的返回值被丢弃
      a, b = Fun_1(), 100,a的值为"Luo1",b的值为100
      return Fun_1(), 100, 200,返回了"Luo1", 100, 200
    所有函数返回值都有效的情况:
      a, b = Fun_1()
      test_table = {Fun_1()}
      return Fun_1()
      return 100, 200, Fun_1(),返回了100, 200, “Luo1”, “Luo2”
    只有这个函数调用在表达式的最后一个时,所有返回值才能被正确接收

  变长参数:
    三个点即代表变长参数:function Fun_name(...)
    使用test_table = {...}这样可以将可变参数列表打包成一个表对象
    也可用以下两个函数显示打包或解包可变参数
      test_table = table.pack(...)
      a, b, c = table.ubpack({...})

IO输入输出

  lua有两种IO模型
    一种是lua自身提供的输入输出流,称为简单IO模型
    另一种是C风格的文件处理,称为完整IO模型

  简单IO模型
    当前输入流:
      进程的标准输入,类似stdin
      io.read()从里面读出来
      io.input(文件名),用该文件替换标准输入
      local old = io.input()空调用可以返回原来的输入流保存

    当前输出流:
      进程的标准输出,类似stdout
      io.write()写进去
      io.output(文件名),用该文件替换标准输出

    io.read():
      io.read("a", "l", "L", "n")  读有很多模式,a表示整个文件,l表示读一行并丢掉换行符,L表示读一行但保留换行符,n代表读一个数字
      io.read(100)          如果直接传一个数字,则是读多少个字符,或者说多少字节
      io.read("n", "n", "n")     连续读三个数组
      任何一次io.read()返回了nil,都表示1到了文件尾

    io.write():
      可以用n多个参数传到write,由wirte拼接:io.write("test", "Luo", "Luo\n")
      也可以string.format拼好后整个传给write:io.write(string.format("%s TestLuoLuo %d", "aaa", 100))

  完整IO模型
    local file = io.open("/etc/xxx", "wr"),可以像c那样操作文件
      成功返回一个流对象
      失败返回三个值,第一个是nil,第二个是错误信息,第三个是错误码
    local txt = file:read("a")
    file:write("xxxx")
    file:close()

  执行系统命令os.execute("shutdown -r now")

if 条件	then
	code
else if 条件 then
	code
else
	code
end

while 条件 do
	code
end

repeat
	code
until 条件

for i = 初始值, 目标值, 每次循环增加多少值 do
	code
end

  goto
  goto的标签定义:::tag::
  然后goto tag
  局部变量的作用域 终止于 最后一个有效句处,而标签的定义是无效语句,也就是说
    do
      local a
      goto tag
      local b
      ::tag:: 在这里是看不到a和b的定义的
    end

泛型for、迭代器

lua的迭代器,理解成:返回集合中下一个元素的函数
泛型for循环保存3个值:
	迭代函数 
	不可变状态(要遍历的对象)	
	控制变量(循环计数或者说本次循环的一个标记,下轮循环根据这个标记来找下一个值)
	
	for 变量列表 in 表达式列表 do
	end
		变量列表:如果变量列表第一个为nil,循环结束,同时也用于保存控制变量
		表达式列表:表达式列表需要且只要三个,多余丢弃,不足nil不足,
				或者说也不是表达式列表,因为大多数时候此处是个函数,这个函数应该返回三个值
			 	这三个值就是前面的迭代函数 不可变状态 控制变量
			 	
	如pairs的实现:
		local function mypairs(t)
			return next, t, nil			//next(t, nil),返回表中的第一组kv,第二参数非nil时,根据第二参数随机返回下一组kv
		end
	
	以下三个for是等价的:
		for k, v in pairs(t) do 
		for k, v in next, t do
		for k, v in next, t, nil do 
		第一次循环,next(t, nil)返回第一组,控制变量存到k
		第二次循环,next(t, k)随机返回下一组
		把next替换成自己写的函数,那就是自己的迭代器了

闭包

局部递归函数的定义:

local digui = 
function(n)
	digui(n-1)
end
编译的时候digui还没有定义,需要
local dogui
digui = 
function(n)
	digui(n-1)
end
这样就有一个对象,虽然编译的时候还没有值,但是调用的时候有

闭包:

在lua中定义一个局部函数,该局部函数是可以访问其作用域内的其他变量的
do
	var = 100
	local f = function(a)		
		print(var)
	end
end

但是如果

function createFuncter()
	var = 100
	local f = function(a)		
		print(var)
	end
	return f
end
local funa = createFuncter();
local funb = createFuncter();

这时候funa和funb都能正确访问一个局部的var变量,并且是两个相互独立的var变量
闭包即:一个函数能正确访问 该函数的 非局部变量 的机制

字符串匹配

  string.find(在哪个字符串里面查, 查找内容, 从哪个索引位置开始查, 是不是简单查询)
    返回两个值,字串的起始索引和结束索引
    第四个参数的意思是:string.find(, “[()]”, 1, “”),圆方括号这些字符会用于类似正则的匹配,如果第四个参数传true,说明是一个简单查询,然后就只是单纯匹配“[”这个字符

  string.match(在哪个字符串里面查, 类似于正则的表达式详见后)
    返回匹配的字符串
  string.gsub(在哪个字符串上操作, 类似于正则的表达式详见后, 把匹配的字符串替换成什么, 如果有多个匹配最多替换几次)
    如果第三参数是一个函数:那么这个函数应该接受匹配的子串作为参数,返回要替换成的目标字符串
    如果第三参数是一个表:使用匹配的子串作为表索引,找到对应的值,这个值就是目标替换的目标字符串
    第一个返回值是被替换后的字符串副本
    第二个返回值是替换了几次

  string.gmatch()

  lua中的字符串匹配规则:
    特殊字符:().%+=*?[]^$
    .  一个点,代表任意字符
    %a  字母
    %bxy 以x开头,y结尾的字符,’b()‘表示匹配一对括号之间的东西,包含括号本身
    %c  控制字符
    %d  数字
    %g  除空格外的可打印字符
    %l  小写字母
    %p  标点符号
    %s  空格
    %u  大写字母
    %w  字符和数字
    %x  十六进制数
    大写代表补集,如%S表示空格外的所有字符

  和前面的某个%组合使用
    +  一次或多次(最长)
    *  零次或多次(最长)
    -  零次或多次(最短)
    ?  零次或一次

  例子:
    %d+/%d+/%d+ 用于匹07/09/2000这样的日期,或者%d%d/%d%d/%d%d%d%d
    在一对方括号[]中的称为字符集:[abcdABCD][0-5a-c]来匹配某些字母或数字,或者[%[%]]来匹配一对方括号
    string.match()可以返回多个字符串,需要做的是把要返回的字符串用()括起来:
      key, val = string.match(“name = luoluo”, "(%a+)%s*=%s*(%a+)")
      print(key, val)输出:name luoluo
      即:在括号内的就打包成一个变量返回

时间

  时间有两种格式:
    ①unix时间戳
    ②类似struct tm的结构(一个表),称为日期表:{year = 2000, month = 7, day = 10, hour = 15, min = 13, sec = 01, yday = xxx, wday = x, isdst = false },实际上在调用对应函数时不是所有成员都是必须的,isdst表示是否为夏令时。

  os.time(日期表)
    不传递参数,返回当前时间戳
    传递一个日期表参数,将该日期表转换成时间戳返回
  os.date(“*t”, 可选传递的时间戳)
    返回一个格式化的时间或者日期表
    os.date(“*t”)就会返回完整的日期表结构
    os.date(“*t”, os.time()),等价于os.date(“*t”)
    os.date(“%Y/%m/%d”, os.time())返回格式化时间戳 2022/12/28

  日期加减计算:
    t = os.date(“*t”)         今天是2022/12/28
    t.month = t.month + 1      此时表结构大概是{year = 2022, month = 13, day = 28}
    t = os.date(“*t”, os.time(t))  才能变成{year = 2023, month = 1, day = 28}

预编译、执行、错误处理

  预编译:lua执行代码前预编译生成二进制文件
    luac -o MyLuaFile.lc MyLuaFile.lua     将lua文件预编译
    lua MyLuuaFile.lc            执行这个预编译好的二进制

  loadfile() 预编译代码,但不会执行,只是预编译
        出错返回两个值,第一个是nil,第二个是错误信息
  dofile() 预编译+执行代码
  load() 从字符串或者函数中加载一段代码段,返回一个函数,调用这个函数可以执行代码
      出错返回值和loadfile()一样
      a = 1
      b = 2
      fun = load("a = a + b")
      fun(); // 执行完a的值为3
      注:load只是简单的执行代码,不会像前面的闭包那样每个都不一样的独立变量
        因为load总是在全局环境加载代码,所有如果定义了a = 1;local a = 2;那么load访问的总是全局的那个,相对的,闭包函数则总是访问离他最近的那个定义

  错误:
    error("错误信息", 2),error函数主动引发一个错误
      第二可选参数是一个层数,假设调用error所在函数fun()调用是第一层,那么2就代表谁调用了fun()那一层
  安全调用:pcall(fun())
    不会引发错误
    成功返回 true,然后返回 fun()的所有返回值
    失败返回false和错误信息

模块

  导入一个模块,这个模块可以是lua编写的其他文件,也可是其他语言的lib什么的
    require "string";然后 string.format()什么的,来访问这个模块里的函数或者变量
    流程:require先在全局package.loaded检查是否已加载,如果已经加载过,那么就不会再执行一次了,除非把这个模块从package.loaded删掉
    没有加载过,从package.path寻找,这也是一个表,包含很多路径,去这些路径里找
    先找对应名字的lua文件,找不到才找同名c库什么的
    保存到package.loaded

  编写一个模块的格式:
    local MyModuleName = {}
    各种代码往MyModuleName里插函数或者变量什么的
    retuern MyModuleName 或者package.loaded["文件名"] = MyModuleName

元表、元方法

  元表:可以为表类型定义加减法之类的操作,或者一些默认的访问行为之类的
  元方法:存在元表中某个字段的函数

  一个表的元表不能直接通过某字段读取,需要通过:
    local MyTable = {}
    local MyMetaTable = {}
    获取一个表的元表:getmetatable(MyTable)
    设置一个表的元表:setmetatable(MyTable, MyMetaTable)

   如果有:
      MyMetaTable.__add = function MyTable(t1, t2) return t1.a + t2.a end
      setmetatable(MyTable, MyMetaTable)
      那么调用 MyTable + {a = 2}的时候,就会来找这个__add对应的函数
      寻找的过程先找运算符左边对象元表的__add,找不到再找右边对象元表的__add
      找不到就抛出异常,但是如果右边不是表、没有a这个成员,报错之类的,应该由用户处理
   类似__add的还有很多:
      __sub   减
      __div    除
      __floor   除
      __unm   负数
      __mod   模
      __pow   幂
      __band   与
      __bor    或
      __bxor   非
      __bnot   反
      __shl    左移
      __shr    右移
      __concat  连接符. .
      __eq    等于
      __lt    小于,对于表是真子集
      __le    小于等于,对于表是子集
      __tostring 到字符串
      __len   #操作符长度
      __metatable 用来保护元表不被修改,若设置了该字段,getmetatable会返回该字段的值,setmetatable则会报错

      __index
             没有设置该元方法时,访问不存在的元素返回nil,这是默认行为
             当设置了该方法,会转而调用该方法返回一个值
               MyMetaTable.__index = function (t, key)
                 return 9999       // 任意都不存在的值都返回999
                 return OtherTable[key] // 或者访问另一张表
               end
               rawget(t, i)        //总是会绕过__index访问原始数据
             如果设置的是一个另一个表:那么使用键访问这个表

      __newindex  
             给索引的赋值时候,如果__newindex没有被设置,默认行为
             如果设置了,不管是函数还是表,都和__index行为类似
             也有rawset(table, key, v)来绕过

使用元表模拟面向对象行为

   冒号运算符:Table:fun1(parm1, parm2)等价于Table.fun1(Table, parm1, parm2)
      冒号运算符总是把冒号左边的对象作为一个参数,隐式传递给冒号右边的函数,作为第一参数
      要在函数中访问这个第一参数,使用self即可,比如return self[parm1]
      主要作用于lua模仿继承行为,概念类似于:传递了一个基类还是派生类对象给这个函数,或者说基类还是派生类对象在调用成员函数

										模拟类和对象

lua里只要声明了,就是对象
	在概念上将其视作对象
	在语言本身上,不管是类还是对象,都是对象

local BaseClassDef = {a=15, b = function (self) return self.a end}		// 在lua本身是一个对象,但将其视为一个模板、类定义
BaseClassDef:c = function () return self.a + self.a end

local BaseClassObj1
setmeatatable(BaseClassObj1, {__index = BaseClassDef})

类定义是:BaseClassDef 
类对象是:BaseClassObj1
访问类对象BaseClassObj1的时候:
	BaseClassObj1.a
	BaseClassObj1.b()
	BaseClassObj1.c()
都是没有的,然后到元表BaseClassDef去找,就能找到了,这些都被封装起来,像是BaseClassObj1有了成员,有了方法

当给a赋值时:
	BaseClassObj1.a = BaseClassObj1.a * 100
BaseClassDef 和 BaseClassObj1 就都有一份独立的a,前者是15,后者是1500

BaseClassDef的对象factory:
	BaseClassDef:MyFactory(t)
		t = t or {}
		self.__index = self
		setmetatable(t, self)
		return t
	end
	BaseClassObj2 = BaseClassDef:MyFactory()
		BaseClassDef:MyFactory内部先生成一个空表对象
		接下来一行看起来并没用,等后面继承补
		setmetatable给新的对象设置元表,这样就能访问数据成员或者成员方法了
		然后返回一个BaseClassDef的对象BaseClassObj2
										模拟继承
BaseClassDef:MyFactory(t)
		t = t or {}
		self.__index = self
		setmetatable(t, self)
		return t
	end

DeviceClassDef = BaseClassDef:MyFactory()		// 这样派生类的定义就可以了,接下来往里面放东西就行了
function DeviceClassDef:fun1(parm1) ...code... end
function fun2(DeviceClassobj, parm1) ...code... end

DeviceClassObj1 = DeviceClassDef:MyFactory()	// 派生类对象有了

重点在于MyFactory的self.__index = self; setmetatable(t, self)这两句
	调用BaseClassDef:MyFactory()时:
		setmetatable(t, self)把BaseClassDef作为元表设置到了新对象、新类DeviceClassDef中
		那么DeviceClassDef访问不存在的元素 -》 检查有没有元表 -》 有元表 -》 找__index -》 __index指向表BaseClassDef -》 尝试在BaseClassDef中找一个元素
	调用DeviceClassDef:MyFactory()时:
		setmetatable(t, self)把BaseClassDef作为元表设置到了新对象DeviceClassObj1中
		当DeviceClassObj1.a时:试图访问不存在的元素 -》 找元表的__index -》 指向表DeviceClassDef -》 a在DeviceClassDef也是不存在的元素 -》 转到上面 -》 最终在BaseClassDef中寻找
										多重继承
懒得写了,到处都是

环境

  一个普通的表(全局表):_G
  _G[“aaa”]直接访问
  _G略有特殊:不允许值为nil,判断有没有某个值要用rawget(_G, “aaa”) != nil

  自由名称:可以理解成没有带local的变量
  全局变量是假的,其行为用特殊变量名_ENV来模拟

  预编译代码前,在所有代码(一个文件内)外层创建local _E在这里插入代码片NV
  所有自由名称xxx替换为_ENV.xxx
  load全局初始化代码段的第一个上值?不太能理解,也许是继承lua运行环境的某个表里的所有值,print之类的东西
    local a
    b = c + a
    类似于
    local _ENV = xxx   --print什么的复制过来?
    local a
    _ENV.b = _ENV.c + a

  a = 1
  local a = 2
  _ENV.a_G.a的值都是1
  大多数时候_ENV、_G指向同一个表,但是_G不管什么时候都是唯一一份,而_ENV在代码上下文中是可变的

  给_ENV赋值一个新表需要注意,因为print之类的在里面,_ENV = {}之后,就不能访问print了,但是_G.print还是可以的
    a = 1
    _ENV = {g = _G}  // 改变了全局的_ENV
               // 如果这里是local _ENV
                那么接下来作用域内的所有自由名称都被这个local _ENV捕获
                超出作用域又回归全局的_ENV捕获
               // function (_ENV) end  _ENV这个特殊名字在函数也有同样的效果
    a = 2
    g.print(1+2) // 在_EVN中的值就像被声明过一样,可以直接用
    _ENV.a 的值是2
    _G.a 的值是1

垃圾回收

  local对象超出作用域被回收,通过collectgarbage("count")查看内存占用
  当一个对象被放入表 声明为全局对象,他就没有办法被回收了

  但是弱引用表除外
  表是否为弱引用取决于元表的__mode字段,其值为“k”、“v”、“kv”之一
  分别代表键是弱引用还是值是弱引用,还是两者都是
  如果一个对象只被一个弱引用表持有(即引用计数1,且这个1来自弱引用表),那么他就会被回收。
  k代表键是弱引用时被回收,kv代表键值任意一个弱引用时被回收,任何一个键值被回收了,整个键值都会从表中删除。

  析构:
    通过元表__gc给对象设置一个回收时调用函数
    但是需要注意,必须在调用setmetatable时元表里有__gcsetmetatable时没有,但后续又给元表添加了__gc方法,是不会调用这个函数的
    按setmetatable的逆序调用他们的析构
    进入析构后就被标记为已析构,只是标记,没有真删

  复苏:
    如果一个对象的析构访问了自己,那么这个对象会复苏,即放到全局变量中
    并且复苏是能传递的,析构访问了其他对象,那么其他对象也会被复苏

  collectgarbage():
    第一个参数是字符串,控制功能
    第二个参数是某些功能需要一些数据,可选项
    “collect”:默认,回收一下垃圾
    “stop”:停止垃圾收集。
    “restart”:重启垃圾收集。
    “count”:返回已使用内存数,包括死掉但还没被回收的对象。
    “step”:大概是分配多少字节后来一次垃圾回收?使用第二参数。
    “setpause”:每隔多久来一次垃圾回收,第二参数是百分比,0%~200%,值越小频率越高。
    “setstepmul”:看不懂干嘛的,默认200%,低于100%会让垃圾回收效率低。

协程

  协程四状态:挂起、运行、正常、死亡
  fun = function () coroutline.yield() end
  thread1 = coroutline.create()返回一个thread类型的值
  coroutline.status(thread1)返回协程的状态,新创建的协程默认挂起
  coroutline.resume(thread1)把协程唤醒,开始或继续执行
  coroutline.yield()遇到这个调用会把协程挂起,直到再次调用coroutline.resume(thread1)

  coroutline.resume(thread1, parm1, parm2, parm3..)
    额外的参数作为fun的参数,或者正在等待的yield的返回值
    第一个返回值是bool, true表示没有错,
    后面的返回值是yield的参数,resume之后才开始调用yield(parm3, parm4…),参数是多少,这里返回值就是多少。
    如果协程结束,这里的返回值就是fun的返回值

C中调用lua

  三个头文件:<lua.h>、<luaxlib.n>、<lualib.h>,还有库文件链接

  大概流程
    lua_State* L = luaL_newstate();  lua和c的交互都基于lua_State对象,
    luaL_openlibs(L);          新对象没有任何状态和预定义函数,该调用将print之类的函数加载进来
    luaL_loadString(L, 某个缓冲区);   从缓冲区读点数据到栈里
    lua_pcall(L, 0, 0, 0)       调用一个lua函数,见后
    lua_pop(L, 1)            从栈顶弹出几个
    lua_close(L)

  lua_State是一个栈,提供一组函数来向lua_State中压入数据:
  第一个压入栈的数据索引为1,然后2、3,-1表示栈顶索引,-2表示栈顶下面那个数据的索引
  很多操作lua_State的函数都要依赖该索引,另外进入栈的数据全部都是原来的副本
    void lua_pushnil (lua_State * L);
    void lua_pushboolean (lua_State * L, int bool);
    void lua_pushnumber (lua_State * L, lua_Number n);double类型
    void lua_pushinteger (lua_State * L, lua_Integer n);64位int
    void lua_pushlstring (lua_State * L, const char * s, size_t len);字符串包含\0之类的用这个
    void lua_pushstring (lua_State * L, const char * s);

  一组函数签名相同的lua函数,用来检查某个栈索引上的数据类型,星号代表各种数据类型:
    lua_is* (lua_State * L, int index);

  一组参数类似但返回值不同的转型函数:
    lua_to*(lua_State * L, int index);
    lua_tostring(lua_State * L, int index, size_t * len); 第三参数是返回了多少字节
    lua_Number lua_tonumberx (lua_State * L, int index, int* isnum);第三参数是是否成功
    lua_Integer lua_tointegerx (lua_State * L, int index, int* isnum);

  操作栈的其他函数:
    int lua_gettpo (lua_State * L);返回栈顶索引,也是元素个数
    void lua_settop (lua_State * L, int index);调整栈的高度,比原来高出的nil填补,比原来低出的丢掉
    void lua_pushvalue (lua_State * L, int index);把索引index上的副本再一次压入栈顶
    void lua_rotate (lua_State * L, int index, int n);看不懂
    void lua_romove (lua_State * L, int index);
    void lua_insert (lua_State * L, int index);
    void lua_replace (lua_State * L, int index);index上的数据的直接弹出,栈顶数据的直接移到这
    void lua_copy (lua_State * L, int startIndex, int endIndex);

  获取和设置全局变量
    lua_getglobal(lua_State * L, const char *) 获取某个全局变量,然后压入栈里
    lua_setglobal (lua_State *L, const char *name) 弹出一个栈顶的值并写到lua全局变量name中

  在c中,不管是调用函数、操作lua表对象,流程大致一样:
    ①把要函数名、lua表对象压入栈
    ②把函数参数、表的键压入栈
    ③调用lua_pcall或者lua_gettable之类的

    获取表的值
      lua_getglobal(L, "table1")获取lua全局变量table1压入栈,他应当是一个表
      lua_pushstring(L, str_key)压入键,这个table对象索引变成-2
      lua_gettable(L, -2)从-2索引这个table对象上操作,使用索引-1的作为键,取到值后把-1索引的键移除,最后把获得的数据又压入L
      lua_pop(L, 1)从栈顶弹出获得数据,栈重新回归高度为1,内部只存了一个table对象的状态

    设置表的值
      lua_getglobal(L, "table2")获取lua全局变量table2压入栈,他应当是一个表
      lua_pushstring(L, str_key)压入键
      lua_pushstring(L, 155)压入值
      lua_settable(L, -3)压入键值后表在栈中的索引变为-3,写入键值后,键值被自动从栈中移除,只剩下表在栈中

    调用函数
      lua_getglobal(L, "fun1")获取lua全局变量fun1压入栈,他应当是一个函数
      lua_pushnumber(L, 1)压入函数参数
      lua_pushnumber(L, 2)压入函数参数
lua_pushnumber(L, 3)压入函数参数
      if(lua_pcall(L, 3, 1, 0) != LUA_OK)表示从L中调用函数,函数有3个参数,1个返回值
        处理错误;
      调用函数完成后,栈被清空,然后将0或多个返回值压入栈中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据提供的引用内容,无法确定您所说的“lua脚本写http请求”是指在lua脚本中发起http请求,还是在接收到http请求后在lua脚本中处理请求。因此,我将为您提供这两种情况的回答。 1. 在lua脚本中发起http请求 可以使用Lua的socket库来发起http请求。以下是一个简单的示例: ```lua local http = require("socket.http") local response, status = http.request("http://www.example.com") if status == 200 then print(response) end ``` 在这个示例中,我们使用socket.http库中的request函数来发起http请求。如果请求成功,我们将打印响应内容。 2. 在接收到http请求后在lua脚本中处理请求 根据提供的引用内容,我们可以看到在nginx配置中使用了content_by_lua_file指令来指定一个lua脚本来处理http请求。因此,我们可以在这个lua脚本中处理http请求。以下是一个简单的示例: ```lua -- 导入http库 local http = require("resty.http") -- 创建http客户端 local httpc = http.new() -- 发起http请求 local res, err = httpc:request_uri("http://www.example.com", { method = "GET" }) -- 检查请求是否成功 if not res then ngx.say("failed to request: ", err) return end -- 打印响应内容 ngx.say(res.body) ``` 在这个示例中,我们使用了OpenResty提供的resty.http库来发起http请求。我们首先创建了一个http客户端,然后使用request_uri函数来发起http请求。如果请求成功,我们将打印响应内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值