Lua

http://www.runoob.com/lua/lua-data-types.html    //菜鸟教程

https://blog.csdn.net/qq_39574690/article/details/80753504  //LUA注意点

https://blog.csdn.net/qq_39574690/article/details/80725308   //xLua热更新总结

https://blog.csdn.net/qq_39574690/article/details/80773837  //uLua热更新知识

https://github.com/wuxiongbin/XIL  //使用ILRuntime实现的类似XLUA功能的Unity3D下热修复BUG的解决方案

http://www.cnblogs.com/slysky/p/7920694.html  //整理Lua和Unity和Lua交互文章链接

https://download.csdn.net/download/tvcctv27tv/10344318  //解决下载超时的问题

一、了解Lua

1. lua语言解决的问题:嵌入应用程序,为应用程序提供灵活的扩展和定制.

2. 特性:轻量级 可扩展  

3. 其他特性:

1》支持面向过程编程和函数式编程      2》自动内存管理,只提供一种通用类型得table,用它可以实现数组,哈希表,集合,对象。    3》语言内置模式匹配:闭包(closure); 函数可以看作是一个值;提供多线程支持。  5》通过闭包和table可以支持面向对象所支持的关键机制,eg数据抽线,虚函数,继承,重载。

二、Lua基本语法

1. 交互式编程

  lua提供了交互式编程模式。在命令行中输入  lua -i   即可启用。

2. 脚本式编程

  <1. 通过ide去编译执行。

  <2. 标识符

    <1> 定义标识符变量和函数:区分大小写的。

    <2> 最好不要用_ABC 即下划线加大写字母的形式,因为Lua的保留字也是这样的,用于Lua内部全局变量  _VERSION。

    Lua 中,字母(letter)的含义是依赖于本地环境的。

    <3. 定义的默认是全局变量; 给变量赋值后默认就创建了这个全局变量 ;访问一个没有初始化的全局变量也不会报错,只不过得到的结果是nil 。

       删除了全局变量只需将变量为nil    b=nil.

三、Lua得数据类型:

1. 数据类型

 Lua是动态类型语言,变量不要类型,只需要为变量赋值。

 Lua有8种基本类型: nil、boolean、number、string、userdata、function、thread、table.

 nil: 表示一个无效值,在条件语句中相当于false; 给全局变量或table赋值nil,相当于删除。

 boolean:  Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true:

 number : 双精度类型的实浮点数。其实只要是实数就是双精度类型。包括0. 

     注意 Lua 中所有的值都可以作为条件。在控制结构的条 件中除了 false 和 nil 为假,其他值都为真。所以 Lua 认为 0 和空串都是真。

 string : 由一对双引号或单引号来表示。也可以是[[  fdasdfads  ]] 表示一块字符串,一般是一个html字符串。

 userdata : 表示任意存储在变量的c数据结构。

 table : 是关联数组。数组索引可以是数字、字符串或表达式。 Lua里,table的创建是通过构造表达式来完成,最简单的构造表达式是{} ,创建一个空表。

 type 来测试类型: 

 print(type(10.4*3))   --> number
 print(type(print))      --> function

 type(X)=="nil"   ---> nil做比较时,加“”来比较。

2.  lua字符串的操作:

字符串使用双引号,单字符使用单引号。模式串也是单引号。

1. 在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字:

print("2"+6)   --> 8

2. 字符串拼接是 .. ;    +号是加法计算,串不能相加时,会报错,和c#不一样,不是连接字符串 ;

3. 计算字符串长度 print(#"www.runoob.com") 

3. 表table:

lua中的数组索引,key是以1开始的。
tab1={};
tab2={key1=100,key2="value"}  --键不能用引号引起来
--print(tab1);
--print(tab1.key);

print(tab2.key1);   --1.直接获取key  
print(tab2["key1"]); --2.通过键的名字获取

遍历:

1. for in pair do 形式 

  lua里有break,但是没contiue.  在lua5.2版本后,可以使用goto continue 来模拟。

for a=1,5 do
	if(a==3) then
	  goto continue
	end
	::continue::
end
for key,val in pairs(tab1) do
print("key",val)
end

2.for  do形式

for i=1,2 do
print("fddsfasd")
end

4.函数

<1. lua中函数可以直接赋值给变量。

<2. 函数可以以匿名形式来传递。

5.thread

6.userdata 自定义类型

四、Lua变量:

1. 全局变量,局部变量,域

2. 赋值语句

多个变量赋值(函数返回多个值)时,变量个数>值的个数,那么多余的赋值为nil.  <值得个数,则多余的值忽略

3. table的索引访问

<1. 和字典的形式一样访问。tab[2]  //此处的2是index,第几个

<2.如果存储的字符串,则可以使用tab.key  //设置key是字符串时才可以这样访问,默认key是从1开始的整数。

五、六、循环语句、流程控制

while、for、repeat...unitl、循环嵌套。

break、goto

七、函数

1.可变参数:

 <1. 和c语言类似,用... 三个点表示可变参数.  lua中可以遍历参数数组。

 <2. 可变参数还可以赋值给一个变量。select("#",...) 可以获取可变参数的数量

 <3. ...  三个点来初始化一个表,再通过遍历这个表,来达到遍历参数个数。

 <4. select("#",...)   获取可变参数的所有个数,包括nil。   

 <5. select("#",tab) 获取tab长度时遇到参数是nil时,则停止计数,并且返回计数。  #tab或者string  是即使有nil,也会计数。

 <5. 如果加固定参数,则固定参数必须是写在可变参数的前边。

function add(...)  
local s = 0  
  for i, v in ipairs{...} do   --> {...} 表示一个由所有变长参数构成的数组  
    s = s + v  
  end  
  return s  
end  
print(add(3,4,5,6,7))  --->25

 

--标识符
b=10
print(type("hello"))
print(type(1.2))
if true then
print("wangzhe")
end


--表 table
tab1={};
tab2={key1=100,key2="value"}  --键不能用引号引起来
--print(tab1);
--print(tab1.key);

print(tab2.key1);   --1.直接获取key
print(tab2["key1"]); --2.通过键的名字获取

tab3={"皅qq","sss"};   --不指定key时相当于数组,索引从1开始
--print(tab3[2])
for key,val in pairs(tab3) do
print(key..":"..val);
end

--表中删除后,索引时不连续的
tab3[2]=nil;

for key,val in pairs(tab3) do
print(key..":"..val);
end
tab3=nil;  --删除整个表


--函数的传递
function fact(n)
	if(n==1) then
		return n;
	else
		return n*2;
	end

end

--函数当类型来使用
fact2=fact;
print(fact2(2));
--函数作为函数的参数传递

--匿名函数
print(function (k,v)
print("匿名函数");
end
);

 

--25   [local]function  局部函数
local function Name(num1,num2)
	if(num1>num2) then
	return num1
	else
	return num2
	end
end

--print(Name(2,3));
--函数的赋值   匿名函数  函数当参数传递


--26  函数的可变参数
function test(...)
	local arg={...}
	res=0
	for k,v in pairs(arg) do
		res=res+v;
		--print(arg[1])  	--会把传进来的参数封装成一个表(arg) 这样获取的arg还得带有一个参数是说明这个表的个数的  遍历表
	end
	print(res);
end

test();
test(2);
test(4,5);
test(11,5,3,9);

--输出
0
2
9
28

八、运算符

1. Lua逻辑运算符

 and 、 or 、not

九、字符串

--30  字符常见操作
str="wang yan jie"
str2=string.upper(str)   --lower   --转换成大写,但是对原有字符不做处理

print(str,str2)

--32 Lua数组的基本特性和定义
--lua的表是键值对的形式,所以索引可以 负数


--33 多维数组

--34 Lua中的迭代器函数
--pairs 遍历表中所有的key和value
--ipairs 按照索引从1开始遍历,递增遍历,遇到nil就停止遍历


--[[for  变量列表 in 迭代函数,状态变量(默认是nil),控制变量  do
	--循环体
end
--]]

--变量列表是根据迭代器的返回值来的,多少个返回值就定义多少个变量列表来接受
--状态变量指挥在第一次调用的时候赋值,相当于是初始化  标注需要迭代多少次数【其实就是数组所带的个实闹谍】

十、Lua数组

1. 可以使用整数索引来访问数组元素,如果索引没有值则返回nil。

2. Lua 索引值是以 1 为开始,也可以指定以0或者负数为索引。

3. Lua中支持多维数组。注意指定是数组的索引值,避免出现nil,节省内存。

不同索引键的三行三列阵列多维数组:根据不同索引键把三维数组存入到一维数组中。

 

十一、Lua迭代器

迭代器:

For遍历格式:

for key=1,3,1 do  --从1迭代到3,迭代步长是1

print(square,3,key)

End

For迭代器格式:

    使用lua默认的迭代器函数ipairs

for k, v in pairs(tab) do

    print(k, v)

End

For迭代器的流程:

首先,初始化,计算 in 后面表达式的值,表达式应该返回泛型 for 需要的三个值:迭代函数、状态常量、控制变量.  square , 3 , 0

第二,将状态常量和控制变量作为参数调用迭代函数(注意:对于 for结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)。

第三,将迭代函数返回的值赋给变量列表。 (i,v)=(currentNumber, currentNumber*currentNumber)

第四,如果返回的第一个值为nil循环结束,否则执行循环体。

第五,回到第二步再次调用迭代函数

无状态迭代器:

优点:无状态的迭代器是指不保留任何状态的迭代器,因此在循环中我们可以利用无状态迭代器避免创建闭包花费额外的代价。应该是不保留上边的控制变量。

多状态迭代器:

迭代器需要保存多个状态信息而不是简单的状态常量和控制变量

保存多状态的方式:

  1. 使用闭包 
    1. 闭包解析:https://www.jb51.net/article/60866.htm

             初步看,由于创建变量i的函数 newCounter 已经返回, 所以每次调用 func 时, 应该是超过了作用范围。其实不然,lua使用了闭包来处理,一个 closure 就是一个函数加上该函数所需访问的所有"非局部的变量"所以上例中 c1, c2 是同个函数所创建的两个不同的 closure, 它们各自拥有局部变量i的独立实例.

function newCounter()
        local i = 0
        func = function()
                i = i + 1
                return i
        end
        return func
end
c = newCounter()
print(c())
print(c())
  1. 将所有的状态信息封装到 table 内,将 table 作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在 table 内,所以迭代函数通常不需要第二个参数。
    1. 使用tab来实现多状态:
array = {"Google", "Runoob"}
count=#array
tab={}
tab["index"]=0
function elementIterator()
      tab["index"]=tab["index"]+1
      if tab["index"] <= count then
         --  返回迭代器的当前元素
         return array[tab["index"]]
      end
end
for key=1,2,1 do
  print(elementIterator(tab))
end

 

--39  Lua中的模块
--对代码做一些分? 局部函数在另一个模块中调用时,放在全局函数中调用?
--变量,函数,封装在一个表中,在另一个表中引用,最后返回modle
--引用时引用的时文件名

Lua_第1张图片

--40 c包

--41 元表  定义对表和表进行之间的操作  定义元方法
	--一个元表只能作为一个表的元表  ,一般情况下元表是对普通表做的扩展,一般是不能修改的

mytable={"Lua","java"}  --普通表
mymetable={}  --元表
mytable=setmetable(mytable,mymetabe)  --此函数的返回值是普通表

--  getmetable(mytable)   得到普通表对应的元表
--  如果元表(metatable)中存在__metatable键值,则setmetable会失败,
    --当设置元表是这个键值对时,当输出普通表对应的元表,则只会输出地__metatable的值,而得不到元表了
	--禁止用户访问和修改元表中的成员或者修改元表



--43 元表中__index的作用:元方法
        --当访问到一个不存在的索引时起作用
	--如果__index包含一个函数的化,Lua会调用这个函数,table和键会作为参数传递给这个数
	--__index元方法查看表中元素是否存在,如果不存在且没有返回值,则返回nil,如果由返回值则返回这个返回值。存在则由__index返回结果,
	--__index后是一张表时,则在普通表中找不到时会在元表中找这个这个键对应的值。处理索引访问不存在的情况。
--注意:如果访问普通表中一个不存在的键时,则会调用元函数做一些事情


--44 元表中的__newindex的作用
--调用时机: 当我们对普通表中的一个新的索引修改时才会起作用  
	--或者给表添加新的键值对时起作用,调用后边跟的函数,后边的函数通过 rawset(table,key,value) ,来加入到这个普通表中
--如果后边跟的时一个表,则添加新键值对时,则会把这个key和value 直接添加到这个后边跟的表中。
	
--如果后边	
	
__newindex=function(table,key,value)  --普通表  修改的key  修改成的值
end

Lua协程



--46  元表中的__call的作用
	--定义这个函数后,就可以把表当函数来使用时,mytable()  __call = Fuction(tab,arg1,arg2)

--47  元表中tostring元方法的作用

--48协程函数



--49  定义和启动协程函数

--定义
--[[
co=coroutine.create(
	function (a,b)
		print(a+b)
	end
	)
--启动
coroutine.resume(co,10,20)   --既可以启动,又可以恢复协程程序

--]]

--[[
--第二种定义方式
co=coroutine.wrap(
	function (a,b)
		print(a+b)
	end
	)

--启动
co(20,30)

--]]

--挂起
co=coroutine.create(
function(a,b)
	print(a+b)
	print(coroutine.status(co))
	coroutine.yield(a/b)  --暂停
	print(a-b)
	return a*b
	end
)

----协程的返回值  返回结果和返回值.中间有暂停时返回值在yiled中传递

result,res1= coroutine.resume(co,10,20)
print("协程启动是否成功  ")
print(res1);
print("i am here")
print(coroutine.status(co))

--协程程序的内部和外部的交流

--状态  函数整个执行完后就是dead状态
--resume是处于主程序中,将外部状态传到协程里面,yield是在协程内部,将数据返回出。

Lua_第2张图片

 

  

 

 

二: Lua基本用法

Table: 如果两个指针指向同一个地址,把其中一个释放后,另一个地址任然在。

Lua_第3张图片

排序注意点:

当我们获取 table 的长度的时候无论是使用 # 还是 table.getn 其都会在索引中断的地方停止计数,而导致无法正确取得 table 的长度。

可以使用以下方法来代替:

function table_leng(t)
  local leng=0
  for k, v in pairs(t) do
    leng=leng+1
  end
  return leng;
end

Lua 模块与包//??

模块其实就是已知元素组成的一个table.调用和table的调用一致。

Lua_第4张图片

????????????

Lua_第5张图片

 

 

使用模块方法:

-- require "模块名"
-- require ("模块名") --模块名并不是表名而是文件名,例如将上面的文件名改为module1.lua,那么下面的也要改为require 'module1'

require "module"  --相当于引用了整个module.lua文件,那个文件的内容会替换掉这句代码,下面开始使用module表

print(module.var)

module.func1()

module.func3()
 

Lua元表(Metatable)//??

对两个表进行操作  “_add”等即时字段,对应一个值(table或者方法),该值 就是“元方法”

setmetatable(mytable,mymetatable)     -- 把 mymetatable 设为 mytable 的元表 

Lua 查找一个表元素时的规则,其实就是如下 3 个步骤:

  • 1.在表中查找,如果找到,返回该元素,找不到则继续
  • 2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
  • 3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,则返回该函数的返回值。

 

4.2 metatable元表概念

4.2.1元表的__index指定方法:

--1. funciton __index
--普通表
mytable={'C#','Java','C++'}
--元表
mymetatable={
    __index=function(tab,key)  --注意:__index 是有2个'_'在前面的,不要写成_index
        print(tab[1]) --tab是元表对应的普表表
        print(key)    --key是在普通表mytable没有找到的键
        return '1212'
    end
}
--设置mytable的元表是mymetatable
mytable=setmetatable(mytable,mymetatable)
print(mytable[3]) -- 访问存在于普通表的键,正常输出C++,而不会去执行元表__index指定的方法
print(mytable['a']) -- mytable['a']返回了一个字符串'1212' 这个字符串的返回是因为执行了__index指定的方法
-- 总结: 当普通表mytable中没有对应的键值对时,会去调用mymetatable元表的__index指定的方法,输出tab(普通表)[1]元素和找不到的键,并返回'1212'字符串

C++

C#

a

212

触发__index的方法是从普通表查不到键时,即这种情况也会触发q=mytable['a']

4.2.2__index指定一个表

--2.__index mytable mymetatable
mytable={'C#','Java','Lua'}
index_table={'XLua','Unity','Hotfix','Look'}
mymetatable={
    __index=index_table    --
当普通表搜不到键值对时会去到__index指定的表搜 ,如果还是找不到,那就返回nil
}
mytable=setmetatable(mytable,mymetatable)
print(mytable[1])--输出 C#
print(mytable[4])--输出 Look (这个是在__index指定的表index_table拿到的)
C#
Look

--------------------- 

4.2.3__newindex指定一个方法

-- __newindex Function
mytable={'c#','Java','phyton'}
mymetatable={
    __newindex=function(tab,key,value)
        print('表[1]'..tab[1])
        print('新的键'..key)
        print('值'..value)
        --如果我要往元表插入数据
        rawset(tab,key,value)
    end
}
mytable=setmetatable(mytable,mymetatable)
mytable[1]='6'
mytable[100]='abc'
print('插入键值对='..mytable[100])

--当对普通表新增键值对时,会调用元表的__newindex指定的方法,tab是普通表,key是新增的键,value是新增的值
表[1]6
新的键100
值abc
abc

--------------

 

->在这里我突发奇想,测试一下mytable[100]='abc'会不会触发__index的方法或表

-- __newindex Function
mytable={'c#','Java','phyton'}
mymetatable={
    __index=function(tab,key)
        print('没找到键='..key)
        return '__index返回给你'
    end,
    __newindex=function(tab,key,value)
        print('表[1]'..tab[1])
        print('新的键'..key)
        print('值'..value)
        --如果我要往元表插入数据
        rawset(tab,key,value)
    end
}
mytable=setmetatable(mytable,mymetatable)
mytable[1]='6'
mytable[100]='abc'
表[1]6
新的键100
值abc
可见,Lua并不是按照一般思路去思考的
对普通表进行赋值操作若新增键值对了,那么会触发__newindex指定的方法或表处理.
--------------------- 

4.2.4__newindex指定一个表

--4 __newindex table
mytable={'C#'}
table={}
mymetatable={
    __newindex=table
}
mytable=setmetatable(mytable,mymetatable)
mytable[1]='6'
mytable[100]='abc'
print(mytable[1]) --输出 6
print(mytable[100]) -- 输出 nil
print(table[1])  -- 输出 nil
print(table[100]) -- 输出 abc

--总结:当对普通表新增键值对的操作,不会作用于普通表,而是作用于元表__newindex指定的表
6
nil
nil
abc

--------------------- 
 



--简单模式文件的读写
--[[
file=io.open("source.txt",r)   --返回文件的句柄,句柄就是控制文件的,方向盘功能
io.input(file)		--表示下边对文件进行输入了
print(io.read())
io.close(file)
--]]

--完全模式  :读取   写入缓冲,减少和磁盘的交互,节省性能
--[[
file=io.open("source.txt",r)
print(file:read());
file:close()
--]]

--Lua垃圾回收机制
--增量标记扫描处理器  ,一个表可以被多个变量引用。扫描有没有被使用
--垃圾收集器间歇率  ,控制收集频率
--垃圾收集器∽最后收集清空



--Lua面向对象
--table引用类型  对一个对象来说就是属性 方法

--[[
person={name="Wyj",age=27}

person.eat=function(self)
	print(self.name.."在撸代码")
end

a=person		--此处person和a都是用的指针,值类型,类似于c#的引用类型,传递的是引用【值类型】
--person.eat(person)
person=nil
a.eat(a)

--]]


--使用:定义的方法,则可以直接使用self,因为self就是代表当前的这个表,系统会自动赋值
--:调用的对象,self代表:前边的对象
--[[
person={name="Wyj",age=27}

function person:eat()
	print(self.name.."在写代码")
end
a=person
a:eat()
--]]


--面向对象的核心
--为了能使得person重复声明对象

person={name="Wyj",age=27}

function person:eat()
	print(self.name.."在写代码")
end

--**************Lua通过new方法构造对象
--__index访问某个值时,如果该值不存在的时候,则会从其元表中访问
--__newindex如果对普通表进行修改时,如果普通表中该值不存在,则会设置在__newIndex对的元表中去,【如果该__newInex对的是一个函数则会调用此函数
function person:new(o)
	t= o or {}    --o等于null的北,则t={},否则t=o
	setmetatable(t,{__index=self})  --调用一个属性时,如果t中不存在,那么会在__index所指定的table中查找
	return t
end

person1=persson:new(nil)
print(person1.name)   --person1调用name的时候,如果t中不存在,则会从index指定的表中进行搜索输出


person2=persson:new({weight = 100})
person2.name="wyj"   --元表的增加值/设置值
print(person2.name)


--62 lesson
--63 继承
Student=person:new()  --使用person构造出来,则有了person中的属性
--再给student添加自己的属性
Student.grade=1;
stu1=Student:new()






 

 

__newindex 元方法//??

__newindex 元方法用来对表更新,__index则用来对表访问 。

当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。

Lua_第6张图片

Lua 协同程序(coroutine)

线程和协同程序区别

线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。

在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。

总结: coroutine.creat方法只要建立了一个协程 ,那么这个协程的状态默认就是suspend。使用resume方法启动后,会变成running状态;遇到yield时将状态设为suspend;如果遇到return,那么将协程的状态改为dead。

coroutine.resume方法需要特别注意的一点是,这个方法只要调用就会返回一个boolean值。

coroutine.resume方法如果调用成功,那么返回true;如果有yield方法,同时返回yield括号里的参数;如果没有yield,那么继续运行直到协程结束;直到遇到return,将协程的状态改为dead,并同时返回return的值。

coroutine.resume方法如果调用失败(调用状态为dead的协程会导致失败),那么返回false,并且带上一句"cannot resume dead coroutine"

resume是从挂起点运行。

-- 可发现,协程的状态是只有在协同程序的方法里面才是运行状态,在外部都是处于挂起或者死亡状态的

--菜鸟教程的案例有误,在外部输出coroutine.running()必然是nil (亲测)

全面解析菜鸟教程的对于resume和yiled的灵活使用

 

Lua 文件 I/O

 

Lua 错误处理

assert 

error (message [, level])

功能:终止正在执行的函数,并返回message的内容作为错误信息(error函数永远都不会返回)

通常情况下,error会附加一些错误位置的信息到message头部。

Level参数指示获得错误的位置:

  • Level=1[默认]:为调用error位置(文件+行号)
  • Level=2:指出哪个调用error的函数的函数
  • Level=0:不添加错误位置信息

pcall(protected call)

pcall(函数 , 要传递给后者的参数),有错误、无错误;返回值true或者或false, errorinfo。

语法格式如下

if pcall(function_name, ….) then
-- 没有错误
else
-- 一些错误
end

Lua 调试(Debug)

Lua 垃圾回收

Lua 采用了自动内存管理。 这意味着你不用操心新创建的对象需要的内存如何分配出来, 也不用考虑在对象不再被使用后怎样释放它们所占用的内存。

1.   垃圾收集器间歇率控制着收集器需要在开启新的循环前要等待多久。 增大这个值会减少收集器的积极性.

2.   垃圾收集器步进倍率控制着收集器运作速度相对于内存分配速度的倍率。 增大这个值不仅会让收集器更加积极,还会增加每个增量步骤的长度。 不要把这个值设得小于 100 , 那样的话收集器就工作的太慢了以至于永远都干不完一个循环。 默认值是 200 ,这表示收集器以内存分配的"两倍"速工作。

Lua 面向对象

Lua 数据库访问

 

301 LuaInterface 学习

什么是LuaInterface : 包含LuaInterface.dll和Luanet.dll .通过此完成c#和Lua的调用

            Program p = new Program();
            //注册普通方法
            lua.RegisterFunction("LuaMethod",p,p.GetType().GetMethod("CLRMethod"));  //参数1 注册进lua后的函数名字  
            //注册静态方法
            lua.RegisterFunction("CLRStaticMethod", null, typeof(Program).GetMethod("CLRStaticMethod"));
            lua.DoString("CLRStaticMethod");
        }
        public void CLRMethod()
        {
            Console.WriteLine("wangyanjie");
        }

        public static void CLRStaticMethod()
        {
            Console.WriteLine("wangyanjie");
        }

在Lua中使用c#中的类:

            //lesson 1
            //生成lua代码
            //lua.DoString("num = 2");
            //lua.DoString("str=' a string '");
            //object[] values = lua.DoString(" return num,str ");
            //foreach (object obj in values)
            //{
            //    Console.WriteLine(obj);
            //}
            //lesson 2
            //执行myLua.lua脚本程序
            //myLua.lua 文件用文本文件编写的话,则一定要使用ANSI格式编码来保存
            //lua.DoFile("myLua.lua"); 

            //lesson 3
            把c#注册进Lua的一个全局方法
            //Program p = new Program();
            注册普通方法  参数1 注册进lua后的函数名字  
            //lua.RegisterFunction("LuaMethod", p, p.GetType().GetMethod("CLRMethod"));  
            注册静态方法
            //lua.RegisterFunction("CLRStaticMethod", null, typeof(Program).GetMethod   ("CLRStaticMethod"));
            调用注册进Lua的方法
            //lua.DoString("LuaMethod()");
            //lua.DoString("CLRStaticMethod()");

在Lua中使用c#的dll和类

require "luanet"

luanet.load_assembly("System")   --已经把c#dll 引入进来了   luanet.dll一般是在lua中访问c#的,在c#过程中运行

luanet.load_assembly("LuaInterface_Study")   --加载dll库

Int32 =  luanet.import_type("System.Int32")
--加载lua中的类,先加载命名空间
Program = luanet.import_type("LuaInterface_Study.Program")

num = Int32.Parse("3435")
print(num)

program1 = Program()
print( program1.name)
program1:TestMethod()  --调用方法

--void,strLength = program1:TestOut("taikr.com")
--print(void,strLength)

--void,count=program1:TestRef("www.taikr.com",10)

--print(void,count)

----------------------------------


c#
         //lesson 4   lua中使用c#中的类
            //lua中把c#dll 引入进来,并且执行c#dll中的方法  ,在c#过程中启动,此时lua中就调用了c#中的方法
            lua.DoFile("script.lua");

 

17  在Lua中访问c#中的方法-特殊情况

        public void TestOut(string name, out int count)
        {
            Console.WriteLine("c# : "+name);
            count = name.Length;
        }

        public void TestRef(string name, ref int count)
        {
            Console.WriteLine(name);
            Console.WriteLine(count);
            count = name.Length;
        }

--------------------------------------------------


--out  ref 的情况,有重载时先匹配第一个函数
-- 在Lua中访问c#中的方法-特殊情况,当函数中有out ref,out和ref参数和函数的返回值一起返回,
--并且调用的时候,out参数不需要传入。

void,strLength = program1:TestOut("taikr.com")  --返回值第一个是null的,所以需要void来接受。第二个是out参数
print(void,strLength)

void,count=program1:TestRef("www.taikr.com",10)  --ref参数需要把值传进来
print(void,count)

AssetBundle:

ManifestFileVersion: 0
CRC: 324281795      //检验码
Hashes:
  AssetFileHash:
    serializedVersion: 2
    Hash: 75b1e3fba0dd26fabf8c61cb4647de4d
  TypeTreeHash:
    serializedVersion: 2
    Hash: 8fe15831e4ad8c37d6024ec822931f85
HashAppended: 0
ClassTypes:         //依赖的类
- Class: 1
  Script: {instanceID: 0}
- Class: 4
  Script: {instanceID: 0}
- Class: 21
  Script: {instanceID: 0}
- Class: 23
  Script: {instanceID: 0}
- Class: 33
  Script: {instanceID: 0}
- Class: 43
  Script: {instanceID: 0}
- Class: 48
  Script: {instanceID: 0}
- Class: 65
  Script: {instanceID: 0}
- Class: 114
  Script: {fileID: 11500000, guid: ab5eac1d15cfc104a96e6828a0ebe9f1, type: 3}
- Class: 115
  Script: {instanceID: 0}
Assets:
- Assets/Cube.prefab      //打包的资源
Dependencies:
- Assetbundle/cube1       //以来的资源【引用了另一个资源的情况】
    string url= "file://E:/NewSystemProject/Lua/MyLua/Assetbundle/Cube";
    string assetsName= "Cube";   //

    private IEnumerator Start()
    {
        using (WWW www = new WWW(url))
        {
            yield return www;
            if (www.error != null)
            {
                Debug.Log("下载出错");
            }
            else
            {
                AssetBundle bundle = www.assetBundle;
                //此处是unity中被打包的资源名字,不是打包出的
                Object obj = bundle.LoadAsset(assetsName);  
                Instantiate(obj);
                //卸载资源
                bundle.Unload(false);
                //dispose()   因为在using()中,所以不需要
            }
        }
    }

30    UI的制作,自己打一个包,用Lua代码加载

按住alt,在锚点界面选择和父类大小保持一致。

打包时,后缀要是GO.assetbundle  ,因为代码中默认是以这个后缀来命名的。

因为,我的UI面板用了sprite图片。所以要把所有的UI图片打包。【图片得考虑分包,不然用到一张图片,就得把所以不用的都解压掉】

build后,把资源打包进StreamingAssets中。此处可以查找各个包得依赖。查看打包后的资源已经在files文件中进行管理了。

--return 所有加载得view对应得lua脚本

--根据c#得代码执行流程,写lua代码

 

--启动lua程序时,直接启动lua可执行文件就可以打开lua代码
--如果在手机端热更新则需要设置服务器ip,把SuperSocket.SocketService.exe启动
--客户端则需要ip和DebugMode  UpdateMode   WebUrl 重新设置下,更新时把代码记得关了

 

 

                                                    Lua 程序设计:

Chunk: 

dofile 在调试或者测试 Lua 代码时是很方便的.可以测一下,重载指定的lua文件,是否可行????

dofile("testLua2.lua")
local d=Add(1,2)
print(d)

第二章 类型和值

Number

local n = a or 0   

lua math.floor  因为这个函数是向下取整,所以lua通过这个函数来实现四舍五入:

lua 中的math.floor函数是向下取整函数。
  math.floor(5.123)  -- 5
  math.floor(5.523)   -- 5
用此特性实现四舍五入
  math.floor(5.123 + 0.5)  -- 5
  math.floor(5.523 + 0.5)  -- 6

String: 

local a=10 .. 20

   ..在 Lua 中是字符串连接符,当在一个数字后面写..时,必须加上空格以防止被解释 错

尽管字符串和数字可以自动转换,但两者是不同的,像 10 == "10"这样的比较永远 都是错的。

如果转成数字可以使用需要显式将 string 函数 tonumber()   [tostring],如果 string 不是正 确的数字该函数将返回 nil。

为了避免不一致的结果,混合比较数字和字符串,Lua 会报错,比如:2 < "15".  "2"<"15" 则是按照字母顺序比较。 2<1 比较,fasle. 

and 和 or 的运算结果不是 true 和 false,而是和它的两个操作数相关。

************************  注意注意
a and b -- 如果 a 为 false,则返回 a,否则返回 b
a or b -- 如果 a 为 true,则返回 a,否则返回 b。 
i = i or 1  i没有初始化过,在把i初始化为1

userdata :

Lua里的三元运算符:

a ? b : c  <==>    (a and b) or c

表的构造

lua里不推荐数组下标从 0 开始,否则很多标准库不能使用。

 

第4章   基本语法

1.多值赋值 : 一般用于值得交换 或 函数的返回值。

<1. 因为lua支持多个变量的同时赋值,所以如果需要交换两个数,则可以直接使用赋值来完成交换。

<2. lua和其他语言不同。如果对多个变量赋值,则必须是依次赋值。a,b,c=0  这种在lua是错误的。

2.lua使用习惯: 避免命名冲突,访问比较快。

3.for

<1. 数值for循环。

for var=exp1,exp2,exp3 do

<2. 泛型for循环。

for i,v in ipairs(a) do print(v) end

  遍历表k的例子:for k in pairs(t) do print(k) end

第4章   基本语法

1. lua函数语法:如果函数只有一个参数,并且这个参数是字符串或者表构造的时

候, ()可以省略
print "Hello World" <--> print("Hello World") 
dofile 'a.lua' <--> dofile ('a.lua') 
print [[ddddd]]

function fun(par)
  print "run fun"
end
local b={1,2,3}
fun {1,2,3}
fun(b)

2. Lua 也提供了面向对象方式调用函数的语法,比如 o:foo(x)o.foo(o, x)是。

3. 可以使用()来把函数包起来,强制函数返回一个参数.

   一个 return 语句如果使用圆括号将返回值括起来也将导致返回一个值。

function foo2 () return 'a','b' end
print((foo2()))   --  a

4. 函数多值返回的特殊函数 unpack

接受一个数组作为函数的输入参数,返回数组的所有元 素。unpack 被用来实现范型调用机制。
Lua 中如果你想调用可变参数的可变函数只需要这样:
f = string.find  --string.find (str, substr, [init, [end]])
                 --在一个指定的目标字符串中搜索指定的内容(第三个参数为索引), 
                 --返回其具体位置。不存在则返回 nil。
a = {"hello", "ll"}
print(f(unpack(a))) --> 3 4 为ll的索引
预定义的 unpack 函数是用 C 语言实现的,我们也可以用 Lua 来完成:
 
function unpack(t, i)
  i = i or 1
  if t[i] then
    return t[i], unpack(t, i + 1)
  end
end

5.2 可变参数

5.3 命名参数

用名字指定函数参数。lua将参数放在一个表中,把表作为函数的唯一参数传递。

当函数的参数很多的时候,这种函数参数的传递方式很方便的
tab= {old="temp.lua", new="temp1.lua"}
function fun(arg)
	print(arg.old)
	print(arg.new)
end
fun(tab)

第6章  再论函数

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

你可能感兴趣的:(Lua,Lua)