本文目录
- 碎碎念
- 一、Lua的集成开发环境
- 二、Lua常用语法
- 三、习题小练
- 参考
碎碎念
鉴于接下去公司的下一个项目又要写Lua代码了,并且进入公司,也是从学习Lua开始,相比于公司里勤勤勉勉,兢兢业业的同事&大神,自己着实好生懒惰,一不经意间,又在蹉跎岁月,虚度时光.但也深信,在一个牛叉的团队里,早晚自己也能变得比较牛B(装在A与C之间),即使难堪大用,也得让自己尽量向他们看齐,总得想法充实并努力跟上吧.同时,回想起当时刚学Lua时的茫然,也希望这文对公司新人在加速并有效学习Lua方面有所帮助.另外,对于没有编程天赋的程序猿,年纪大了,记性也不好了,什么都要记下来才比较放心,也为方便以后用到时查找复习吧.诚然,相比于公司里的大神,这点水准,实属于班门弄斧,但这已无关紧要,能把自己会的一点知识分享出来,帮助别人在学习过程中少走弯路,甚至起到抛砖引玉,引发技术探讨,对自己本身也是个促进和巩固的过程.于是乎,废话不多说,想来无事就从复习Lua开始吧.
至于Lua怎么好,这些就不废话多说了,个人简单粗暴的认为,只要是实用的,高效的,公司项目需要的,它就是好的,值得学习的.这里也只是简明的概要一下自己在工作中,学习并简单使用的历程,主要是个人感觉比较重要的一些知识要点的小结.因为长篇大论书籍对初学者来说,的确也很容易挫伤自己的学习热情,而简明精华的要点与实践,才是我们共同追求.
那么正所谓,工欲善其事,必先利其器,磨刀不误砍柴功,有一款好的Lua集成开发环境,对于我们快速并高效地学习Lua肯定大有裨益.只有站在前人的基础上,我们才能走的更高,看得更远.(这里我补充一点,承认有轻微强迫症的人,对于那种有好的集成开发工具不用,而坚持使用纯文本开发的,我不觉得他有多牛叉,而觉得他像是个傻叉.)当然,仅限是个人观点,个人喜好,对事不对人哦.
一. Lua的集成开发环境
由于每个程序猿的技术背景不同,熟悉的开发工具就不太一样,那么请先看这里: Lua开发相关
1. Lua for IntelliJ IDEA
Lua for IntelliJ IDEA 是一款 IDEA 集成开发环境的插件,用来支持对 Lua 编程语言的开发。支持语法高亮、代码重构等基本功能。Lua for IntelliJ IDEA 1.0a40 发布,该版本增加了基本数据类型推断。

相关链接
2. Lua集成开发环境 Decoda
Decoda 是一个开源的 Lua 集成开发环境和调试器。需要 premake4 项目文件进行构建。

相关链接
* Decoda详情
3. Eclipse的Lua开发插件LDT
对于熟悉Java开发的程序猿,对Eclipse应该是比较熟悉的,那么在Eclipse上加插件写Lua代码应该是个不错的选择.而LDT (Lua Development Tools) 为 Lua 开发者提供了 Eclipse 开发 Lua 应用的插件。

相关链接
* LDT插件
由于本人是Java技术背景,习惯使用Eclipse,因此后面的实例采用的是Eclipse+LDT插件的方式学习并演示Lua.还有就是工作中项目用的Mac+Sublime Text2作为编译调式工具.至于其它零零总总,五花八门的开发工具,不甚了解,也不想了解,有一个熟知的开发工具,便于学习理解和动手实践就够了,这里就不舍本求末了,有兴趣的读者,或者有需要的,自行再去了解.
3.1 Eclipse+ LDT (Lua Development Tools)插件的安装
(1) 到 Eclipse官网 下载 Eclipse IDE for C/C++ Developers 这个版本,原因呢,Lua是被设计成与C/C++很容易整合的语言么,当道就首先这个集成开发环境了.

(2) 安装LDT插件,就像安装普通Eclipse插件一样.

或者参照: 插件安装
具体操作: 在高于Eclipse 4.3+ 以上选择菜单Help --> Install New Software 然后到

然后点击下一步,Finish后重启Eclipse,检查Preferences首选项中,有无Lua选项,并创建Lua工程验证即可!
环境搭建好了,那么,我们就可以更愉快地开始我们的Lua之旅了.
相关链接
* 官网详情
二. Lua常用语法
作为有一定经验的猿,一些比较简单明了的基础语法,这里就不一一重述了,只选择性的说一下Lua特有的语法,或者常用的和容易混淆的语法.
Lua是动态类型语言,变量不需要类型定义.Lua中有8个基本类型分别为nil,boolean,number,string,userdata,function,thread和table.函数type可以测试给定变量或者值的类型.
1. 语句
1 print("Hello World") --输出字符串: "Hello World" 2 print(type(type)) --> function 3 print(type(10.4*3)) --> number(type为判断类型函数)
结果:
注: Lua是类C的,所以,他是区分大小写的。Lua脚本语句的结尾,分号是可选的.
1 -- 两个减号是行注释 2 3 --[[ 4 5 这是块注释 6 7 这是块注释 8 9 --]]
3. 变量
另外,需要注意的是:lua中的变量如果没有特殊说明,全是全局变量,那怕是语句块或是函数里。变量前加local关键字的是局部变量。将全局变量置为nil,意思是删除这个变量.
优先使用局部变量可以:
1. 避免命名冲突
2. 访问速度比全局变量更快
对于全局变量,Lua也是用Table来管理全局变量的,Lua把这些全局变量放在了一个叫“_G”的Table里。
我们可以用如下的方式来访问一个全局变量(假设我们这个全局变量名叫globalVar):
1 _G.globalVar 2 _G["globalVar"]
1 -- 遍历全局变量Table _G 2 for k, v in pairs(_G) do 3 print(k, v) 4 end
4. 表达式&运算符
1) 运行时,Lua会自动在string和number之间自动进行类型转换.
2) a and b --如果a为false,则返回a,否则返回b
a or b -- 如果a为true,则返回a,否则返回b
3) 一个很实用的技巧: 如果x为false或者nil则给x赋初始值v
x = x or v <==> if not x then x = v end
4) Lua中的三元运算符 (a and b) or c

5) 连接运算符 .. --两个点,如果操作数为数字,Lua将数字转成字符串
6) break语句用来退出当前循环(for,repeat,while).在循环外部不可以使用.
5. 控制语句
1 -- while循环 2 sum = 0 3 num = 1 4 while num <= 100 do 5 sum = sum + num 6 num = num + 1 7 end 8 print("sum =",sum)
1 -- if-else分支 2 if age == 40 and sex =="Male" then 3 print("男人四十一枝花") 4 elseif age > 60 and sex ~="Female" then 5 print("old man without country!") 6 elseif age < 20 then 7 io.write("too young, too naive!\n") 8 else 9 local age = io.read() 10 print("Your age is "..age) 11 end
从上面可以看到: “~=”是不等于,而不是!=, 字符串的拼接操作符“..”, 条件表达式中的与或非为分是:and, or, not关键字。
同时注意:Lua没有++或是+=这样的操作.
1 -- 普通for 循环 2 -- 从1加到100 3 sum = 0 4 for i = 1, 100 do 5 sum = sum + i 6 end
1 --until循环 2 sum = 2 3 repeat 4 sum = sum ^ 2 --幂操作 5 print(sum) 6 until sum >1000
6. 函数(Lua的函数和Javascript的很像)
1). 递归
1 -- 1.计算数n的阶乘 2 function fact(n) 3 if 0 == n then 4 return 1 5 else 6 return n * fact(n - 1) 7 end 8 end 9 10 print("请输入数n: ") 11 number = io.read("*number") 12 print(tostring(number).."的阶乘为: "..tostring(fact(number)))
执行结果:
2). 闭包
1 -- 调用newCounter()返回一个function,而这个function引用了newCounter()函数内部的局部变量local i 2 ---------------------------- 3 function newCounter() 4 local i = 0 5 return function() 6 i = i + 1 7 return i 8 end 9 end 10 11 c1 = newCounter 12 print(c1()) --> 1 13 14 newCounter = nil -- 就算我把这个函数销毁了 15 print(c1()) --> 3 还是生效
在Lua中,所有的变量都是“指针”。所有的变量都是从堆里分配出来的,不像C与C++,局部变量是从栈里分配,一旦函数退出,所有局部变量都要被释放。Lua中的所有变量都是从堆里申请的。对象的释放是自动进行的,只有这个对象的引用计数为0了才会被释放掉。
1 -- 示例二 2 function myPower(x) 3 return function(y) return y^x end 4 end 5 6 power2 = myPower(2) 7 power3 = myPower(3) 8 9 print(power2(4)) --4的2次方 10 print(power3(5)) --5的3次方
3). 函数的返回值
Lua一条语句上赋多个值,如: name, age, bGay = "haoel", 37, false, "haoel@hotmail.com"
上面的代码中,因为只有3个变量,所以第四个值被丢弃。
函数也可以返回多个值:
1 function getUserInfo(id) 2 print(id) 3 return "haoel", 37, "haoel@hotmail.com", "http://coolshell.cn" 4 end 5 6 name, age, email, website, bGay = getUserInfo()
注意:上面的示例中,因为没有传id,所以函数中的id输出为nil,因为没有返回bGay,所以bGay也是nil。
4). 局部函数
函数前面加上local就是局部函数
1 -- 比如:下面的两个函数是一样的: 2 function foo(x) return x^2 end 3 foo = function(x) return x^2 end
5). 尾调函数
当函数的最后返回结果是调用另一个函数,称之为尾调函数。Lua的在调用尾调函数时,先是弹出当前函数的栈空间,然后再调用尾调函数,从而降低了函数层层调动过程中的栈消耗,非常适用于函数递归调用。
7. Table
所谓Table其实就是一个Key Value的数据结构,它很像Javascript中的Object,在别的语言里叫Dict或Map,Table长成这个样子:
1 t = {name = "ChenHao", age = 37, handsome = True}
1 -- table的CRUD操作 2 t = {name = "ChenHao", age = 37, handsome = True} 3 4 t.website = "http://coolshelll.cn/" --增 5 local age = t.age --查 6 t.handsome = false --改 7 t.name = nil --删 8 9 for key, value in pairs(t) do 10 print(key,value) 11 end 12 13 14 --访问方式 15 t = {[20] = 100, ['name'] = "lzz", [3.14] = "PI"} 16 print(t[20], t["name"], t[3.14])
执行结果:
注意细节:
1 -- Lua中,表的索引推荐是从1开始的,不是0 2 Polyline = { color = "blue", thickness = 2, npoints =4, 3 {x = 0, y = 0}, 4 {x = -10, y = 0}, 5 {x = -10, y = 10}, 6 {x = 0, y = 10} 7 } 8 9 print(Polyline["color"]) 10 print(Polyline.color) 11 print(Polyline[1]) 12 print(Polyline[1].x)
执行结果:

从上可以看出, 表中的元素都是由key-value组成。如果没有指定key,那就默认以1开始的整数做key,
如上4个{x,y}。如果指定了名称,则以string类型为key,如color, thickness, npoints。
其实,表的key还可以为table, function, file, boolean任意类型.value可以为任何Lua类型。
Person = {["name"] = "Peter", ["age"] = 28} -- 等价于
Person = {name = "Peter", age = 28}
{x=0, y=0} <--> {["x"]=0, ["y"]=0}
{"red", "green", "blue"} <--> {[1]="red", [2]="green", [3]="blue"}
数组相关:
1 -- 数组细则 2 arr = {10, 20, 30, 40, 50} 3 --等价于 4 arr = {[1]=10, [2]=20, [3]=30, [4]=40, [5]=50} 5 6 arr = {"string", 100, "haoel", function() print("coolshell.cn") end} 7 --其中的函数可以这样调用 8 print(arr[4]()) 9 10 --Lua中的数组是从1开始的,#arr为数组长度 11 for i=1, #arr do 12 print(arr[i]) 13 End注:上面的程序中:#arr的意思就是arr的长度。
注:上面的程序中:#arr的意思就是arr的长度。
在Lua中习惯上数组下标从1开始,Lua标准库与此习惯保持一致,否则无法直接使用标准库的函数.
执行结果: 
1 -- 数组操作 2 local a = {10,20,30} 3 table.insert(a,1,15) --指定位置插入 4 table.sort(a) --排序 5 6 --遍历 7 for index,value in ipairs(a) do 8 print(index,value) 9 end 10 11 table.remove(a,2) --移除
结果: 
8. MetaTable 和 MetaMethod
MetaTable和MetaMethod是Lua中的重要的语法,MetaTable主要是用来做一些类似于C++重载操作符式的功能。
比如,我们想实现分数间的相加:2/3 + 4/7,我们如果要执行: fraction_a + fraction_b,会报错的。
* setmetatable(table, meta_table) 设置元表
* getmetatable(table) 获取元表
所以,我们可以动用MetaTable,于是可以这么做:
1 -- 15.MetaTable 和 MetaMethod 2 -- MetaTable主要是用来做一些类似于C++重载操作符式的功能 3 4 -- 实现两个分数相加: 2/3 + 4/7 5 fraction_a = {numerator=2, denominator=3} 6 fraction_b = {numerator=4, denominator=7} 7 8 fraction_op = {} 9 function fraction_op.__add(f1, f2) 10 ret = {} 11 ret.numerator = f1.numerator * f2.denominator + f2.numerator * f1.denominator 12 ret.denominator = f1.denominator * f2.denominator 13 return ret 14 end 15 16 -- 为之前定义的两个table设置MetaTable:(其中的setmetatble是库函数 17 setmetatable(fraction_a, fraction_op) 18 setmetatable(fraction_b, fraction_op) 19 20 -- 调用的是fraction_op.__add()函数 21 fraction_s = fraction_a + fraction_b 22 23 print("fraction_s的类型: ",type(fraction_s)) 24 for key,value in pairs(fraction_s) do 25 if "numerator" == key then 26 print("分子",value) 27 else 28 print("分母",value) 29 end 30 End
执行结果: 
至于__add这是MetaMethod,这是Lua内建约定的,其它的还有如下的MetaMethod:

表相关:
1 __index = function(tb, key) 2 __index = tb
访问索引,如果执行读取一个表中的操作,而这个表里又没有这个域,那么Lua就去查询metatable中的__index域。如果__index是表, 那么就去查__index表中有没有这个域,如果有就从__index这个表里的这个域里去取值。如果__index是函数,那么就调用 __index(tb, key)函数。
1 __newindex = function(tb, key)
更新索引,在更改表域的时候,如果这个表中没有这个域,那么就会从元表的__index里去找。与__index同理。
这两个东西,在类继承里用到.
9. 面向对象
上面我们看到有__index这个重载,这个东西主要是重载了find key的操作。这操作可以让Lua变得有点面向对象的感觉,让其有点像Javascript的prototype。
所谓__index,说得明确一点,如果我们有两个对象a和b,我们想让b作为a的prototype只需要:
1 setmetatable(a, {__index = b})
例如下面的示例:你可以用一个Window_Prototype的模板加上__index的MetaMethod来创建另一个实例:
1 Window_Prototype = {x=0, y=0, width=100, height=100} 2 MyWin = {title="Hello"} 3 setmetatable(MyWin, {__index = Window_Prototype})
于是:MyWin中就可以访问x, y, width, height的内容了。(注:当表要索引一个值时如table[key], Lua会首先在table本身中查找key的值, 如果没有并且这个table存在一个带有__index属性的Metatable, 则Lua会按照__index所定义的函数逻辑查找)
有了以上的基础,我们可以来说说所谓的Lua的面向对象。
1 Person={} 2 3 function Person:new(p) 4 local obj = p 5 if (obj == nil) then 6 obj = {name="ChenHao", age=37, handsome=true} 7 end 8 self.__index = self 9 return setmetatable(obj, self) 10 end 11 12 function Person:toString() 13 return self.name .." : ".. self.age .." : ".. (self.handsome and "handsome" or "ugly") 14 end
上面我们可以看到有一个new方法和一个toString的方法。其中:
1)self 就是 Person,Person:new(p),相当于Person.new(self, p)
2)new方法的self.__index = self 的意图是怕self被扩展后改写,所以,让其保持原样
3)setmetatable这个函数返回的是第一个参数的值。
于是:我们可以这样调用:
1 me = Person:new() 2 print(me:toString()) 3 4 kf = Person:new{name="King's fucking", age=70, handsome=false} 5 print(kf:toString())
继承如下,Lua和Javascript很相似,都是在Prototype的实例上改过来改过去的。
1 Student = Person:new() 2 3 function Student:new() 4 newObj = {year = 2013} 5 self.__index = self 6 return setmetatable(newObj, self) 7 end 8 9 function Student:toString() 10 return "Student : ".. self.year.." : " .. self.name 11 end
10. 其它Lua的标准库
1) math库
1 -- 2.沟股定理 2 function sulcusSharesTheorem(x,y) 3 return math.sqrt(x^2 + y^2) 4 end 5 print("沟3股4,弦: "..tostring(sulcusSharesTheorem(3,4)))
结果: 
2) string库
1 -- string的格式化输出 2 --输出数学PI的3.14%形式 3 print(string.format("%.2f", math.pi) .. "%") 4 --输出数学PI的整数部分 5 print(string.format("%.0f", math.pi))
结果: 
1 -- 常见字符串操作 2 s = "abcdefg" 3 print("字符串长度: ",string.len(s)) 4 print("重复3次s的字符串",string.rep(s,3)) 5 print("创建8个a的字符串",string.rep("a",2^3)) 6 print("转大写",string.upper(s)) 7 print("转小写",string.lower(s)) 8 print(string.char(97)) 9 10 i = 99 11 print(string.char(i,i+1,i+2)) 12 print(string.byte("abc")) 13 print(string.byte("abc",2)) 14 print(string.byte("abc",-1))
结果: 
3) os库(clock,date,time)
1 -- 通过函数os.clock()计算执行程序花费的时钟秒数 2 local x = os.clock() 3 local s = 0 4 for i = 1,100000000 do s = s + 1 end 5 6 print(string.format("elapsed time: %.2f\n",os.clock() - x))
结果:
1 -- 时间日期格式化 2 print("当前时间毫秒值: ",os.time()) 3 --时间日期信息表 4 dateTime = os.date("*t",os.time()) 5 print("时间日期类型: ",type(dateTime)) 6 7 for key,value in pairs(dateTime) do 8 if "day" == key then 9 print(value .. "日") 10 elseif "month" == key then 11 print(value .. "月") 12 elseif "year" == key then 13 print(value .. "年") 14 elseif "hour" == key then 15 print(value .. "时") 16 elseif "min" == key then 17 print(value .. "分") 18 elseif "sec" == key then 19 print(value .. "秒") 20 elseif "wday" == key then 21 print("这个星期第" .. value .. "天") 22 elseif "yday" == key then 23 print("这一年第" .. value .. "天") 24 elseif "isdst" == key then 25 print(value, " true if daylight saving") 26 end 27 --print(key,value) 28 end
结果: 
参数说明:

1 -- 其它处理方式 2 print(os.date("%a,%A")) 3 print(os.date("%b,%B")) 4 print(os.date("%c")) 5 print(os.date("%d")) 6 print(os.date("%H")) 7 print(os.date("%I")) 8 print(os.date("%M")) 9 print(os.date("%m")) 10 print(os.date("%p")) 11 print(os.date("%S")) 12 print(os.date("%w")) 13 print(os.date("%x")) 14 print(os.date("%X"))
结果: 
4) io库
-- 输入一个数,用error函数抛出非数字的错误信息.
1 print("enter a number: ") 2 m = io.read("*number") 3 if not m then error("invalid input") end 4 5 print("enter another number: ") 6 n = assert(io.read("*number"),"invalid input")
执行结果: 
11. 加载文件与运行
当我们需要加载与运行已有文件中的Lua代码时,可以用以下几种方式:
(1) loadstring( str ) --- 加载字串
1 f = loadstring "a = 12; print('a=' .. a)" 2 f() --> a=12
loadstring()本是函数,由于函数是string,所以没有加括号。loadstring()执行完之后,只是加载解析,并没有执行。返回的是一个function类型。执行该函数便可以运行。相当于:
1 f = loadstring "function() a = 12; print('a='..a) end"
(2) loadfile( file_name ) --- 加载文件
这个函数相当于从文件里读出string,然后再调用loadstring(file_text)实现加载功能。
(3) dofile( file_name ) --- 加载并执行文件
相当于loadfile()之后,返回一个函数,再调用这个函数。
1 function dofile( file_name ) 2 local f = assert(loadfile(file_name)) 3 f() 4 end
(4) require( file_name )
这个函数是通过调用dofile()来实现的。不同的是,每次加载执行一个文件时,require()都会记录,避免重复加载。另外,如果给定的路径找不到文件,require()会到指定的路径下去找输到加载的文件。文件名称可以省去.lua后缀。
我们可以直接使用require(“model_name”)来载入别的lua文件,载入的时候就直接执行那个文件了。比如,我们有一个hello.lua的文件:
1 print("Hello, World!")
如果我们:require(“hello”),那么就直接输出Hello, World!了。
注意:
1)require函数,载入同样的lua文件时,只有第一次的时候会去执行,后面的相同的都不执行了。
2)如果你要让每一次文件都会执行的话,你可以使用dofile(“hello”)函数
3)如果你要玩载入后不执行,等你需要的时候执行时,你可以使用 loadfile()函数,如下所示:
1 local hello = loadfile("hello")
2 ... ...
3 ... ...
4 hello()
loadfile(“hello”)后,文件并不执行,我们把文件赋给一个变量hello,当hello()时,才真的执行。
当然,更为标准的玩法如下所示。
假设我们有一个文件叫mymod.lua,内容如下:
文件名:mymod.lua
1 local HaosModel = {}
2
3 local function getname()
4 return "Hao Chen"
5 end
6
7 function HaosModel.Greeting()
8 print("Hello, My name is "..getname())
9 end
10
11 return HaosModel
于是我们可以这样使用:
1 local hao_model = require("mymod")
2 hao_model.Greeting()
其实,require干的事就如下:(所以你知道为什么我们的模块文件要写成那样了)
1 local hao_model = (function ()
2 --mymod.lua文件的内容--
3 end)()
三. 习题小练
1. 构造一个反向表,交换key-value的位置
1 --3.构造一个反向表,交换key-value的位置 2 days = {"Sunday","Monday","Tuesday","Wednesday", 3 "Thursday","Friday","Saturday"} 4 5 --构造一个反向表 6 revDays = {} 7 for i,v in ipairs(days) do 8 revDays[v] = i 9 end 10 11 --打印反向后表的key,value 12 for key,value in pairs(revDays) do 13 print(key,value) 14 end
执行结果: 
2. pairs(泛型遍历集合和数组)与ipairs(遍历出带索引的数组)的区别
1 -- pairs(泛型遍历集合和数组)与ipairs(遍历出带索引的数组)的区别 2 3 a = {"aaa",a="哈哈", y=30, "ddd"} 4 5 for k, v in pairs(a) do 6 print(k, v) 7 end 8 9 print(a[1] .. " --------------- " .. a["y"]) 10 11 for i, v in ipairs(a) do 12 print(i, v) 13 end
执行结果: 
3. 创建一个n行m列矩阵
1 -- 6. 创建一个n行m列矩阵 2 function createMatrix(N,M) 3 local mt = {} --create the matrix 4 for i = 1,N do 5 mt[i] = {} --create a new row 6 for j = 1,M do 7 mt[i][j] = i * j 8 end 9 end 10 return mt 11 end 12 13 --验证n行m列矩阵 14 local tab = createMatrix(2,3) 15 for i = 1,2 do 16 for j = 1,3 do 17 print(tab[i][j]) 18 end 19 End
执行结果: 
4. 以字母顺序打印出这些函数名
1 -- 以字母顺序打印出这些函数名 2 lines = { 3 luaH_Set = 10, 4 luaH_Get = 24, 5 luaH_present = 48 6 } 7 8 temp = {} 9 --将函数名放到一个数组内 10 for n in pairs(lines) do table.insert(temp, n) end 11 table.sort(temp) 12 13 for i,n in ipairs(temp) do print(n) end 14 15 print("------------------------") 16 17 function pairsByKeys(t, f) --可选参数f指定排序方式 18 local a = {} 19 for n in pairs(t) do table.insert(a, n) end 20 table.sort(a, f) 21 local i = 0 -- iterator variable 22 local iter = function() -- iterator function 23 i = i + 1 24 if a[i] == nil then return nil 25 else return a[i],t[a[i]] 26 end 27 end 28 return iter 29 end 30 31 for name, line in pairsByKeys(lines) do 32 print(name, line) 33 end
执行结果: 
参考
如果你还比较喜欢Lua的话,下面是几个在线文章你可以继续学习之:
Lua官网 Lua官方网站
book.luaer.cn lua在线lua学习教程
由于本人对Lua面向对象等的使用和理解还不深刻,这里参考了博文 酷 壳 – CoolShell.cn,
和 Lua学习总结 这里感谢这两位位博主!
由于对于Lua与C/C++的交互部分也不熟悉,因此这里就不作过多陈述了.
同时对此文感觉还是有点用的,欢迎给伦家点个攒,因为被认可也是一种幸福和动力~~.
From: sunriselzz