1、lua中的标识符可以是由任意字母、数字和下划线构成的字符串,但不能以数字开头。
2、lua将通常类似"_VALUE"的标识符作为保留标识符
3、lua的保留字
and break do else elseif
end false for function if
in loacl nil not or
repear return then true until
while
有大小写之分

4、行注释--
块注释--[[ …… ]]
==============================================================
全局变量
lua中访问一个未初始化的变量不会引发错误,结果是一个nil。
如果要删除某个全局变量的话置其为nil
==============================================================

**************************************************************
2、类型与值
lua是动态类型的语言
lua中有8中数据类型
nil、boolean、number、string、userdata、
function、thread、table
eg:print(type(5)) -->number

false和nil规定为假,其余为真
但有一点不同,在条件测试中,将数字零
还有有空字符串也都视为真。

lua中的字符串是不可变值
eg:
a="hello world"
b=string.gsub(a, "world", "lua");
lua字符串和其他lua对象(table或函数等)一样
都是自动内存管理机制所管理的对象。

可以用[[ …… ]]来界定一个字母字符串
eg:page=[[
i like lua
i like c++
i like java
]]
如果第一个字符是换行字符,那么lua会忽略它。

数字与字符串自动转换,lua会尝试将该字符串转换成数字
但是最好不要依赖
----------------

..是字符串连接操作符

如果需要显示地将一个字符串转换成数字,可用tonumber,当不能正确
表示时返回nil

若要转换成字符串,可以调用tostring或者与空字符串连接。

在lua5.1中,可以在字符串前放置操作符“#”来获取改字符串的长度

5、table
table类型实现了"关联数组"。
可以以一种简单、统一和高效的方式来表示普通数组、符号表、
集合、记录、队列、和其他数据结构。
lua也是通过table来表示模块、包和对象的。
eg:io.read
表示"io模块中的read函数"
对于lua,这表示"使用字符串read"作为key来索引table.io
把table理解为对象
eg:
a = {}
k = "x"
a[k] = 10;
a[20] = "great";

当程序再也没有一个table的引用时,lua的垃圾收集器最终会删除该table
并复用其内存

a["name"] -->a.name
a.x -->表示a["x"],表示以字符串"x"来索引table
a[x] -->表示以变量x的值来索引table

//若要表示一个传统的数组或线性表
a={}
for i=1,10 do
a[i]=io.read()
end

lua通常以1作为索引的起始值。

打印a中所有元素
for i=1,#a do
print(a[i])
end

5.1中,长度操作法"#"用于返回一个数组或线性表的最后一个索引值
table.maxn() 返回一个table的最大正索引数,这是lua 5.1的新函数
5.0中可以用talbe.getn(a)获取

6、function
在lua中,函数是作为"第一类值"来看待的。
这表示函数可以存储在变量中,可以通过参数传递给其他函数
还可以作为其他函数的返回值。

7、uerdata(自定义类型)和thread(线程)
userdata用于表示一种由应用程序或C语言库所创建的新类型。
*************************************************************
3、表达式
1、算术操作符
+、-、*、/、^、%、-(负号)

2、关系操作符
<、 >、 <=、 >=、 ==、 ~=

对于table、userdata以及函数,lua是作引用比较的。

3、逻辑操作符
and or not

对于and,如果第一个操作数为假,就返回第一个操作数
否则返回第二个操作数。[即哪个假返回哪个除非都是真则返回第二个]

对于or,如果第一个操作数为真,就返回第一个操作数,否则返回
第二个操作数[即哪个真返回哪个除非都是假则返回第二个]

and的优先级高于or

4
字符串的连接 ..

5、优先级
^
not # -
* / %
+ -
..
< > <= >= -= ==
and
or

6、table构造器
其他方式
a = {"1","2","3"}
a = {x=10, y=20} --> a = {} a.x=10 a.y=20;

lua很少会用到链表,列表数据一般是通过数组实现。

op={["+"]="add", ["-"]="sub"}
i=20;
s="-"
op2={[i+0]=s,s[i+1]=s..s}
[]这种格式允许在方括号之间,
显shi地用一个表达式来初始化索引值

事实上 {x=0,y=0} --> {["x"]=0,["y"]=0}
{"r","g","b"} --> {[1]="r",[2]="g",[3]="b"}
*********************************************************
4、语句

1、
lua允许多重赋值,即对对多个值赋予多个变量
即 a,b = 10, 2*x
2、
j=10 --全局变量
loacl i=1 --局部变量

在交互模式中,每行输入内容自身就形成了一个程序块。
如果一条声明语句没有初始化赋值,那么它声明的所有bianliang都会被初始化为nil

3、
1、if then else \ elseif
2、while value do ... end
3、repeat .... until ... 为真的时候结束
4、在lua中,一个声明在循环体中的局部变量的作用域包括了条件测试
这是5.1的新功能。

5、for语句有两种形式 数字型for和泛型for
--数字型for
for var=exp1,exp2,exp3 do .... end exp3默认为1可以不指定
如果不想给循环设置上限,那么可以使用常量math.huge
--泛型for
通过一个迭代器函数来遍历所有值
for i, v in ipairs(a) do print(v) end
ipairs是一个用于遍历数组的迭代器函数
io.lines 用于迭代文件中每行
pairs 用于迭代table元素
string.gmatch 用于迭代字符串中单词

*******************第5章 函数***********************
1、
所有kua标准程序库中的函数都是用C语言编写的。
lua具有一项非常与众不同的特征,允许函数返回多个结果。
eg:
s,e=string.find("hello lua world", "lua")
--> 7,9 返回起始与结尾索引

function foo0() end 无返回值
function foo1() return "a" end
function foo2() return "a","b" end

当foo2出现在一个表达式中时,luia会将其返回值数量调整为1
eg:print(foo2() .. "lua") -- alua

类似return f() 这样的语句将返回f的所有返回值
print((foo2())) --将迫使它返回一个值

unpack函数,它接收一个数组作为参数,并从下表1开始返回该数组的所有元素,重要用途用于"泛型调用"机制中。

2、变长参数

function add(...)
local s=0
for i, v in ipairs{...} do --注意括号为{}
s=s+v
end
return s
end

function foo(a,b,c) <--> function foo(...)
第二种形式更简洁

function args(...)
local a,b,c=...
print(a,b,c);
end

lua提供了专门用于格式化文本string.format
以及输出文本io.write的函数

用函数select()访问可变形参

select("#",...) 返回形参总数
select("n",...) 返回第n个形参

3、具名实参

*******************第6章 深入函数****************************

第一类值 表示在lua中函数与其他传统类型的值具有相同的权利。
可以存储到变量中或table中,可以作为实参传递给其他函数
还可以作为其他函数的返回值。

词法域 指一个函数可以嵌套在另一个函数中,内部函数可以
访问外部函数中的变量。

a={p=print}
a.p("hello world");

一个函数定义实际上是一条赋值语句

function foo(x) return 2*x end -> foo function(x) return 2*x end

table.sort 排序 ??

1、closure是指一个函数及一系列这个函数会访问到"非局部变量"。
function sortByGrade(name,grades)
table.sort(name,function(n1,n2) return grades[n1] > grades[n2] end) end

比如grades

function newCounter()
local i = 0;
print("enter")
return function() i = i + 1 return i end end
非局部变量--i
回调函数

创建一个安全的运行环境-所谓的沙盒sandbox--closure

2、非全局的函数

Lib={}
Lib.foo=fucntion(x,y) return x+y end
Lib.goo=fucntion(x,y) return x-y end

Lib={
foo=fucntion(x,y) return x+y end,
goo=fucntion(x,y) return x-y end
}

Lib={}
fucntion Lib.foo(x,y) return x+y end
fucntion Lib.goo(x,y) return x-y end

--------
local f = fucntion(...) body end
local g = function(...) body .. f() .. end -- f是可见的
-------
local function f(...) body end

当lua展开局部函数定义的“语法糖”时,并不是使用基本函数定义语法。
而是对于局部函数定义
local function foo(...) body end
lua将其展开为
local foo
foo = function foo(...) body end

向前声明
local f,g
function g() ... end
function f() g() end

3、尾调用
当一个函数调用时另外一个函数的最后一个动作时,该调用才算是一条尾调用。
eg:fucntion f(x) return g(x) end
g(x)执行完能够返回到调用f的点上,即抛弃f

一条“尾调用”就好比是一条goto语句。
在lua中的应用就是编写状态机

尾调用消除可以防止栈溢出。

******************第7章 迭代器与泛型for**************************

1、

每一个迭代器都需要在每次成功调用之间保持一些状态,这样才能知道它所在的位置以及如何进到下一个位置。
closure对于这类任务提供了极佳的支持。

2、泛型for
泛型for在循环过程内部保存了迭代器函数
实际上它保存着3个值
一个迭代器函数、一个恒定状态和一个控制变量
for <var-list> in <exp-list> do
<body>
end

<exp-list>通常只有一个元素,即一个对迭代器工厂的调用

for所做的第一件事情就是对in后面的表达式求值。这些表达式应该
返回3个值供for保存:迭代器函数、恒定状态和控制变量的初值

类似多重赋值...之后 for会以恒定状态和控制变量来调用迭代器函数

3、无状态的迭代器
就是自身不保存任何状态的迭代器。
因此可以在多个循环中使用同一个无状态的迭代器,
避免创建新的closure开销。

典型例子就是 ipairs

8、具有复杂形态的迭代器
通常,迭代器需要保存许多状态,
但是泛型for只提供了一个恒定状态和一个控制变量用于状态的保存。
一个解决方法是closure。或者使用table保存多个字段

----------尽可能编写无状态迭代器
----------基于closure实现会比table更为高效。因为开销廉价
而且访问“非局部变量”比table字段更快。

******************第8章 编译执行与错误**************************

dofile用于运行lua代码块
loadfile不会运行代码,只是编译代码。然后将编译结果作为一个函数返回

如果需要多次运行一个文件,那么只需调用一次loadfile后
多次调用它的返回结果就好了。对于dofile来说,开销更小。

loadstring有点类似loadfile,不同之处在于它是从一个字符串中读取代码,而不是文件读取。

f=loadstring("i=i+1") --> f = function() i = i+1 end

但是第二种代码快得多,

只在编译对应程序块时被编译一次
而调用loadstring时都被重新编译

loadstring在编译时不涉及词法域,这是因为总是在全局环境中编译它的字符串
loadstring最典型的用处是执行外部代码,也就是那些位于程序之外的代码。
loadstring的期望输入是一个程序块,也就是一系列语句
如果需要对一个表达式求值,则必须在其之前添加return才能
构成语句。

string.rep("*",f())根据指定次数复制一个字符串

loadstring("a=1") --> function(...) a=1 end

----error-----
对于lua,通常嵌入在应用程序中,因此发生错误时
不能简单地崩溃或退出。
相反,应该结束当前程序块并返回应用程序。

print "enter a number"
n = io.read("*number")
if not n then error("invalid input") end

--> print "enter a number" n = assert(io.read("*number"), "invalid input")
--因为类似if not<condition> then error end 通用所以被build-in在assert中

lua提供的所有关于动态链接库的功能都聚集在一个函数中 package.loadlib(path, "function name")
将一个C函数作为一个Lua函数返回,如果错误返回nil

loadlib是一个非常底层的函数
通常使用requir来加载C程序库,它会搜索指定的库,然后用loadlib来加载库,并返回初始化函数

----------handle and catch-------------
大多应用程序会处理lua的异常。
如果需要lua自己处理异常,需要使用pcall函数来包装

function trackback()
local status, err = pcall(function() a = "a" + 1 return a end)
print(status, err)
end

function trackback()
local status, err = pcall(function() error("what the fuck") end)
print(status, err)
end

返回bool值以及包含错误行数的错误信息

******************第9章 协同程序 coroutine**************************

协同程序与线程差不多
一条执行序列,拥有自己独立的栈,局部变量和指令指针
同时又与其他协同程序共享全局变量和其他大部分东西

lua将所有有关协同程序的函数放置在一个名为 "coroutine"的 table中
create用于创建新的协同程序,参数为函数,返回值为thread类型

function testCreate()
co = coroutine.create(function() print "hi" end)
print(co)
end

4种不同状态
挂起suspended
运行running
死亡dead
正常normal

当create后,不会自动运行,处于suspended状态

resume是在保护模式中进行的,如果一个协同程序在执行中发生任何错误
lua是不会显示错误消息的,而是返回给resume调用。

可以通过一对resume-yield来交换数据
第一次调用resume时
并没有对应的yield在等待它
因此所有传递个resume的额外参数都将视为协同程序主函数的参数。

yield返回的额外值就是对应resume传入的参数。

function pass_data()
co = coroutine.create(
function(a,b,c)
print("co", a, b, c);
end
)
return co
end

function pass_to_yield()
co = coroutine.create(
function(a, b)
coroutine.yield(a+b, a-b)
end
)
return co
end

协同程序的经典实例 生产者与消费者

过滤器filter 过滤器是一种位于生产者和消费者之间的处理功能
可用于对数据的一些变换。它既是生产者又是消费者。

类似Unix的pipe
协同程序也是一种多线程。但协同程序是非抢占式的
--socket.lua--以后再仔细看。

******************第10章 完整实例 以后查看*************************

*******************************************************************
* *
* 第二部分 *
* *
*******************************************************************

********************** 第11章 数据结构 ****************************

在lua中,table是所有数据结构的基础

使用整数来索引table即可在lua中实现数组。a = {} #a用来获取数组长度
在lua中的约定是一般以1作为数组的起始索引。

在lua中,有两种方式用来表示矩阵

一种是 table的每一个元素是另一个table

function multi_array()
N = 3;
M = 3;
mt = {}
for i = 1, N do
mt[i] = {}
for j = 1, M do
mt[i][j] = 0
end
end

print(mt[2][2]);
end

比起C等创建多维数组
例如三角矩阵可以只占用原来的一半空间

第二种方式是将两个索引合并为一个索引 -- 稀疏矩阵

--链表
function link_array()
list = nil
while true do
x = io.read()
if x == "r" then
break
end
list = { next = list, value = x}
end

print("----------------")
while list do
print(list.value)
list = list.next
end
end

--队列与双向队列

在lua中实现队列的一种简单方法是使用table库的函数insert和remove
但是对于比较大的结构,移动开销很大,一种高效方法是使用两个索引,用于首尾元素

==作为以后参考例子

--集合与无序组 --有些不懂 以后再看

--字符串缓冲

io.read("*all") 可一次性读取文件
使用table作为缓冲区,使用table.concat将给定列表的所有字符串连接起来,并返回结果

table.concat与 io.read("*all")的算法类似 -- 以后再看吧

--图 以后再看吧...

********************** 第12章 数据文件以及持久性 ****************************

Entry({
"JAY",
"Fantasy",
"21",
"1991"
})

local path = "../data/persistent.txt"
local count = 0;
function Entry()count = count + 1 end
dofile(path)
print(count);

采用了事件驱动的做法,Entry函数作为一个回调函数

--串行化 [有环无环 ... ]
将数据转换为一个字节流或字符流
然后将其存储到一个文件或者通过网络连接发送出去

********************** 第13章 元表与元方法 ****************************

lua中每个值都有一套预定义的操作集合,如数字相加等。但无法将两个table相加,此时可通过元表修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定操作。

访问机制
一般的元方法都只针对Lua的核心,也就是一个虚拟机。它会检测一个操作中的值是否有元表,这些元表是否定义了关于次操作的元方法。例如两个table相加,先检查两者之一是否有元表,之后检查是否有一个叫“__add”的字段,若找到,则调用对应的值。“__add”等即时字段,其对应的值(往往是一个函数或是table)就是“元方法”。

setmetatable(只能用于table)和getmetatable(用于任何对象)

setmetatable (table, metatable),对指定table设置metatable
【如果元表(metatable)中存在__metatable键值,setmetatable会失败】

tmeta = getmetatable (tab),返回对象的元表(metatable)
【如果元表(metatable)中存在__metatable键值,当返回__metatable的值】

********************** 第14章 环境 ****************************

lua的所有全局变量保存在一个常规的table
中,这个table称为环境..environment
将table自身保存在一个_G中

---具有动态名字的全局变量
what is meta-programming? --例子有些难懂 以后看

--全局变量声明
lua中的全局变量不需要声明就可以使用 --例子有点奇怪

--非全局的环境
lua允许每个函数拥有一个自己的环境来查找全局变量

可通过setfenv(1, {})改变一个函数的环境,一旦设置会失去之前所有全局变量
第一个参数是一个函数和一个新的环境table

另一种组装新环境的方法是使用继承。

每个函数以及某些closure都有一个继承的环境。

a= 5
function factory()
return function() return a end
end

f1 = factory();
f2 = factory();

print(f1());
print(f2());

setfenv(f1, {a = 10})
print(f1());
print(f2());

print---------------------------------------------------------
5
5
10
5
--------------------------------------------------------------

每一个新创建的函数都继承了创建它的函数环境

********************** 第15章 模块与包 ****************************

模块系统的一个主要目标是允许以不同的形式来共享代码

一个包就是一系列模块

require 用于使用模块
module 用于创建模块

如果require为指定模块找到了一个lua文件
则通过loadfile来加载该文件
如果找到的是一个C程序库,则通过loadlib来加载。

loadfile和loadlib都只是加载了代码,并没有运行它们

假设路径为
?;?.lua;c:\windows\?;/user/local/lua/?/?.lua
require会用模块名来替换每个?
根据替换结果检查是否存在这样的文件。
如果不存在就下一项。

LUA_PATH
LUA_CPATH

一般通过模块来使用他们
有时一个模块有不同版本

---编写模块的基本方法
最简单的:创建一个table
并将所有需要到处的函数放入其中
最后返回这个table

一个模块无返回值的话
require就会返回package.loaded[modname]的当前值

---使用环境
让模块的主程序块有一个独占的环境

--module函数
module()

--子模块与包

看的好晕-------------------------------

********************** 第16章 面向对象编程 ****************************

lua中的table就是一种对象。

table与对象一样可以拥有状态。
table也与对象一样拥有一个独立于其值的标识self
table与对象一样具有独立于创建者和创建地的生命周期

Account = {balance = 0}
function Account.withdraw(v)
print(Account.balance)
Account.balance = Account.balance - v
print(Account.balance)
end

a = Account
Account = nil
Account.withdraw(100.00); --error
------------------------------------------

Account = {balance = 0}

function Account.withdraw(self, v)
print(self.balance)
self.balance = self.balance - v
print(self.balance)
end

a1 = Account
Account = nil

a1.withdraw(a1, 100.00)

lua使用冒号,隐藏self参数。

Account = {balance = 0}

function Account:withdraw(v)
print(self.balance)
self.balance = self.balance - v
print(self.balance)
end

a1 = Account
Account = nil

a1:withdraw(100.00)

lua没有类的概念
对象是没有类型的。而是每个对象都有一个原型。

如果有对象a和b,要让b作为a的原型
a = {};
b = { value = 100};
setmetatable( a, {__index = b})

-----------继承

Account = {balance = 0}

function Account:new(o)
o = o or {}
self.__index = self
setmetatable(o, self)
return o
end

function Account:deposit(v)
self.balance = self.balance + v
end

function Account:withdraw(v)
if v > self.balance then error "insufficient funds" end
self.balance = self.balance - v
end

SpecialAccount = Account:new()

s = SpecialAccount:new({limit = 1000.00})

function SpecialAccount:getLimit()
return self.limit or 0;
end

function s:getLimit()
return 200
end

--重写
function SpecialAccount:withdraw(v)
if v > self.balance then error "超过余额~" end
if v > self:getLimit() then error "not get more than" end
self.balance = self.balance - v
end

s:deposit(1000.00)
s:withdraw(100.00)
print(s.balance)

--多重继承【以后再看】

--私密性

Smalltalk规定所有变量都是私有的,但所有的方法都是公有的。
第一个面向对象语言Simula则不提供任何形式的私密性保护。

Lua也没有私密性保护。
定位于 开发中小型的程序。

通过两个table来表示一个对象
一个table用来保存对象的状态
另外一个用于对象的操作

function newAccount(initialBalance)
--用于保存对象的内部状态
local self = {balance = initialBalance}

local withdraw = function(v) self.balance = self.balance - v end
local getBalance = function() return self.balance end
--返回了一个供外部使用的函数
return {
withdraw = withdraw,
getBalance = getBalance
}
end

acc1 = newAccount(100.00)
acc1.withdraw(40.00)
print(acc1.getBalance());

--单一方法做法 【以后看看】

********************** 第17章 弱引用table ****************************

Lua采用了自动内存管理
垃圾回收器只能回收它认为是垃圾的东西
不能回收用户认为是垃圾的东西

当一个对象处于数组中时,它就无法被回收。

weak table 用来告诉lua一个引用不应该阻碍一个对象的回收

不管是哪一种类型的弱引用table
只要有一个key或value被回收了
那么它们所在的整个条目都会从table中删除。

一项通用的编程技术是“用空间换时间”
例如记录下函数的计算结果,然后当调用同一个函数时
便可复用之前的运行结果

-- memoize method
local results = {}
function mem_loadstring(s)
local res = results[s]
if res == nil then
res = assert(loadstring(s))
results[s] = results
end
return res
end

虽然有些命令会重复出现,但还有许多命令只发生一次。
会消耗内存..因此得用弱引用table

local results = {}
setmetatable(results, {__mode = "v"})
function createRGB(r, g, b)
local key = r.."-"..g.."-"..b
local color = results[key]
collectgarbage()
if color == nil then
color = {red = r, green = g, blue = b}
results[key] = color
end

return color
end

对象属性 与 回顾table的默认值 以后看看--

**************************************************

第18章 到 第20章 先跳过

**************************************************

********************** 第23章 调试库 ****************************

调试库并没有提供一个Lua的调试器
而是提供了一个便写调试器所必须具有的原语。
其性能不高,而且用户也不希望使用。

debug=nil --删除库

调试库由两类函数构成
自省函数:允许检查一个正在运行中程序的各个方面
钩子:允许跟踪一个程序的执行

栈层。

t = debug.getinfo(foo) 得到一个table 里面包含了字段

当用一个数字<n>调用debug.getinfo(n)
就可以得到相应栈层上函数的数据

1--可以得到调用debug.getinfo的那个函数的数据
如果n大于栈中函数总数时,返回nil。

可以让getinfo获取指定信息

---访问局部变量[不知道怎么用]

debug.getlocal来检查任意活动函数的局部变量
参数:函数栈层,变量的索引。
返回:变量的名字,当前值。

Lua按局部变量在一个函数中的出现顺序为他们编号
但编号只限于在函数的当前作用域中活跃的变量。

debug.setlocal改变局部变量的值
参数:函数栈层,变量的索引,新值
返回:变量名

局部变量只有执行过它们的初始化代码后才可见。

---访问非局部变量[不知道怎么用]

getupvalue可以访问一个lua函数所使用的非局部变量。

[被一个函数所引用的“非局部的变量”会一直存在着,
即使这个引用它的函数已经执行完毕了--closure]

参数:函数closure,变量索引
返回

setupvalue

---------------------------------------
--访问其他协同程序 --- 看不懂 唉 以后看

----钩子
钩子机制
可注册一个钩子函数,这个函数会在程序运行中某个特定事件发生时被调用。

debug.sethook
钩子函数
字符串 描述了需要监控的事件
可选的数字 用于说明多久获得一次count事件

--性能剖析 profile

---------------------第4部分--------------------------------

------------------------第24章 C API概述-----------------------------

lua是一种嵌入式语言
即lua不是一个单独运行的程序而是一个可以连接到其他程序的库。
通过链接就可以将lua的功能合并入这些程序。

事实上,Lua解释器是一个简单的应用程序。
Lua的解释器程序(lua.c)就是“应用程序代码”的一个实例

lua解释器依靠lua库来实现主要功能。
这个程序会处理与用户的交互,会将用户的文件或字符串
输入lua库,由lua库来完成主要工作。

C API是一组能使C代码与lua交互的函数。
其中包括读写lua全局变量
调用lua函数
运行一段lua代码
以及注册C函数以供lua代码调用 等

lua与C语言通信的主要方法是一个虚拟栈。
几乎所有API的调用都会操作这个栈上的值。

“lua.h”定义了Lua提供的基础函数 -- 保持原子性和正交性,所有定义以lua_前缀
“lauxlib.h”定义了一个辅助库(使用lua.h中API编写的一个较高的抽象层)
--侧重于解决具体的任务。所有定义都是以luaL_开头
Lua的所有标准库编写都用到了辅助库。

lua库中没有定义任何全局变量
所有状态保存在动态结构lua_State中

所有C API都要求传入一个指向该结构的指针

luaL_newstate函数用于创建一个新环境(或状态)--不包含预定义函数。
“lualib.h”定义了打开这些库的函数--辅助库函数luaL_openlibs则可以打开所有的标准库

luaL_loadbuffer
用来编译用户输入的每行内容。
没有错误则返回0并压入栈

lua_pcall将程序块从栈中弹出
并在保护模式中运行,返回0表示没有错误

lua_tostring可获取消息

lua_pop可弹出删除

lua的核心是不会直接将任何内容写到任何输出流中
当发生错误时,它只会返回错误代码或错误消息来通知调用者。

lua与C之间交换数据时有两个问题:
1、动态类型与静态类型区别
2、自动内存管理与手动内存管理区别

-----------------------------------------------------------------
联合数据类型(Union)是一种特殊的数据类型。
它可以实现:以一种数据类型存储数据,以另一种数据类型来读取数据。
-----------------------------------------------------------------

Lua的设计目标不仅仅是为了便于C/C++访问,还可以被比如Java、Fortran、C#
等语言访问。
Lua使用了垃圾回收机制,如果将一个lua table保存在一个C变量上
lua引擎无法搜索出,有可能会被回收。

对于每种lua中的C类型,API都有一个对应的压入函数。

lua_checkstack 用于检查栈是否有足够的空间

Lua API使用索引(从1[栈底]开始或从-1[栈顶]开始)
lua_is* -- 不会检查值是否为数字类型,而是检查值能否转换为数字类型
lua_type -- 返回栈中元素的类型
lua_to* -- 用于从栈中获取一个值

当lua调用一个C函数返回时,lua就会清空它的栈。
这形成了一条规则,不要在C函数之外使用在C函数内获得的指向lua字符串的指针。

lua_gettop -- 返回栈中元素个数,也可以说栈顶元素的索引! 【切记】

---------------------------------------------------------
lua_open是5.0时代的产物,5.1是luaL_newstate的宏,5.2里面已经没有了..

luaL_newstate用C运行库的内存分配函数。
lua_newstate可自定义内存分配函数。
--------------------------------------------------------------------

C没有提供异常处理机制
lua使用C语言中setjmp机制,类似于异常处理的机制。

在lua中有许多地方可能会发生内存分配错误。
用抛出错误 longjmup , 而不是返回错误..
longjmp

当编写库代码(被lua调用的C函数)
当编写应用程序代码(调用lua的C代码)

大多数应用程序包括lua解释器程序都采用让代码在保护模式下运行
它们调用lua_pcall来运行lua代码。

如果要保护那些与lua交互的C代码
可以使用lua_cpcall

当一个C函数检测到一个错误时
就应该调用lua_error
lua_error函数会清理lua中所有需要清理的东西
然后跳转会发起执行的那个lua_pcall
并附上一条错误消息

------------------------第25章 扩展应用程序-----------------------------

Lua的一项重要用途--作为一种配置语言(configuration language)

------------------------第26章 从Lua调用C-----------------------------
扩展Lua的一项基本含义就是,应用程序将新的C函数注册到Lua中。

Lua能调用部分C函数,并非任意。
有些扩展支持Lua调用任意C函数,但是不可移植且不安全。

C和Lua之间遵循着一个简单的协议才能够进行通信

每一个函数都有自己的局部私有栈。
栈不是一个全局性的结构。

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

所有注册到Lua中的函数都具有相同的原型

typedef int (*lua_CFunction) (lua_State *L);
在lua中是以函数指针的形式调用函数,
并且所有的函数指针都必须满足这种类型。

只有一个Lua状态的参数和一个表示压入栈中的返回值数量。
返回后lua会自动删除栈中结果之下的内容

C模块----------------------------------------------

Lua模块是一个程序块chunk,其中定义了一些Lua函数
这些函数通常存储为table的条目。

一个为Lua编写的C模块可以模仿这种行为。

除了C函数的定义外
还必须定义一个特殊函数(相当于lua模块的主程序块)
它应该注册模块中所有的C函数

Lua通过这个注册过程记录下C函数
使用这些函数地址直接调用它

通常C模块中有一个公共外部函数
用于创建C模块
而其他所有函数都是私有的声明为private

如何将C代码编译成动态链接库
lua便可以使用require 去加载。

LuaL_register(L,"","")

------------------------第27章 编写C函数的技术 [先跳过]-----------------------------
这一章介绍了如何通过C语言编写新函数来扩展Lua

数组操作

------------------------第28章 用户自定义类型 [先跳过]-----------------------------

如何用C编写新类型来扩展Lua

------------------------第29章 管理资源 [先跳过]-----------------------------

------------------------第30章 线程和状态 -----------------------------

Lua不支持共享内存的抢先式多线程。

1、ANSI C没有提供这样的功能。
2、不是一个好的选择

....
抢先式的线程和共享的内存 会有些无法预料的问题..比如..

Lua的协同程序是协作式的 collaborative
可避免不可预知的线程切换所带来的问题
另外
Lua的多个状态之间不共享内存。

--------------------------------
多个线程
----------------------------------------------------------------
在Lua中,一个线程本质上就是一个协同程序。
从C API的角度上看 将线程想象成一个栈可能更形象些。

当调用Lua C API的大多数函数时
这些函数都作用与某一个特定的栈。

只要创建了一个Lua状态
Lua就会自动在这个状态中创建了一个新线程。
称之为主线程。
主线程永远不会被回收
当使用lua_close关闭状态时
它会随状态一起释放。

lua_newthread可以在一个状态中创建其他的线程。

不要使用未被正确系缚
[指一个Lua对象既不在栈中,
又不为其他任何Lua对象所引用的情况]
的线程。有可能已经被垃圾回收。

切记必须确保改线程的引用被持有,才能正常使用。

当创建了一个新的线程后,就可以像主线程那样来使用它。

lua_xmove(F, T, n)可以在两个栈之间移动lua值。
它会从F中弹出n个元素并压入T中

使用多线程的主要目的是实现协同程序。......

lua_resume(Lua_State *L, int narg);

narg指定参数的个数

lua_resume可以启动以一个协同程序
类似lua_call
--压入函数--压入参数--压入参数数量

如果正在运行的函数交出[yield]了控制权
lua_resume就会返回一个特殊的代码LUA_YIELD
并将线程置于一个可以被再次恢复执行的状态

通常以一个Lua函数作为一个协同程序来启动
这个Lua函数可以调用其他Lua函数。

一个C函数只有在返回时才会交出控制权。
因此C函数实际上是不会停止自身执行的。
但如果调用者是一个lua函数
那么如果C函数调用lua_yield就可以挂起lua的调用者。

---------------------------------------
Lua状态
---------------------------------------------------

每次调用luaL_newstate都会创建一个新的lua状态。
不同的lua状态时各自完全独立的,他们之间不共享任何数据。
不能之间沟通需要辅助代码完成---

----------------------------------------该节有些复杂---以后看吧

------------------------第31章 内存管理 -----------------------------

Lua对其内存使用具有严格控制
当关闭一个Lua状态时
Lua会显示地释放它的所有内存。

luaL_newstate会一个默认的分配函数来创建lua状态malloc-realloc-free

若要控制lua的内存分配
则使用原始lua_newstate

---------

==========================================================================================

From example...

Lua中一般以_开头的变量作为特殊变量

而_却经常作为 dummy variable

a="single 'quoted' string and double \"quoted\" string inside"
b='single \'quoted\' string and double "quoted" string inside'

swap two variables
------------------------
print(a,b)
a,b=b,a
print(a,b)
------------------------

print(address.StreetNumber, address["AptNumber"])

-- Conditional assignment.
-- value = test and x or y

a=1
b=(a==1) and "one" or "not one"
print(b)

-- is equivalent to
a=1
if a==1 then
b = "one"
else
b = "not one"
end

=====================================================

for a=1,6,3 do
io.write(a.." ")
end

步长为3

关于Lua程序设计{读书笔记}的更多相关文章

  1. javascript高级程序设计读书笔记-事件(一)

    读书笔记,写的很乱   事件处理程序   事件处理程序分为三种: 1.html事件2. DOM0级,3,DOM2级别  没有DOM1 同样的事件 DOM0会顶掉html事件   因为他们都是属性  而 ...

  2. AngularJS高级程序设计读书笔记 -- 大纲篇

    零. 初衷 现在 AngularJS 4 已经发布了, 楼主还停留在 1.x 的阶段, 深感自卑. 学习 AngularJS 的初衷是因为, 去年楼主开始尝试使用 Flask 开发自动化程序, 需要用 ...

  3. 《The Evolution of Lua》读书笔记 1

    lua的优点: 可移植性 容易嵌入 体积小 高效率 这些优点都来自于lua的设计目标:简洁.从Scheme获得了很多灵感,包括匿名函数,合理的语义域概念   lua前身: 巴西被禁运,引入计算机软件和 ...

  4. javascript高级程序设计读书笔记

    第2章  在html中使用javascript 一般都会把js引用文件放在</body>前面,而不是放在<head>里, 目的是最后读取js文件以提高网页载入速度. 引用js文 ...

  5. Javascript高级程序设计读书笔记(第六章)

    第6章  面向对象的程序设计 6.2 创建对象 创建某个类的实例,必须使用new操作符调用构造函数会经历以下四个步骤: 创建一个新对象: 将构造函数的作用域赋给新对象: 执行构造函数中的代码: 返回新 ...

  6. Java核心技术卷一基础知识-第12章-泛型程序设计-读书笔记

    第12章 泛型程序设计 本章内容: * 为什么要使用泛型程序设计 * 定义简单泛型类 * 泛型方法 * 类型变量的限定 * 泛型代码和虚拟机 * 约束与局限性 * 泛型类型的继承规则 * 通配符类型 ...

  7. Java核心技术卷一基础知识-第7章-图形程序设计-读书笔记

    第7章 图形程序设计 本章内容: * Swing概述 * 创建框架 * 框架定位 * 在组件中显示信息 * 处理2D图形 * 使用颜色 * 文本使用特殊字体 * 显示图像 本章主要讲述如何编写定义屏幕 ...

  8. JavaScript高级程序设计-读书笔记(2)

    第6章 面向对象的程序设计 创建对象 1.最简单方式创建Object的实例,如 var person = new Object(); person.name = “Greg”; person.age ...

  9. 新标准C++程序设计读书笔记_类和对象

    面向对象的程序设计方法 抽象:将某类客观事物共同特点(属性)归纳出来,形成一个数据结构(可以用多个变量描述事物的属性):将这类事物所能进行的行为也归纳出来,形成一个个函数,这些函数可以用来操作数据结构 ...

随机推荐

  1. c#读取文本文档实践3-写入到文本本文档

    首先通过File.ReadAllLines()方法读入文本文档中内容并返回字符串数组contents,这样每行数据就成为了这个字符串数组contents的一个元素,再利用split()方法将每一个元素 ...

  2. python解无忧公主的数学时间097.py

    python解无忧公主的数学时间097.py """ python解无忧公主的数学时间097.py codegay 2016年3月30日 00:17:26 http:// ...

  3. Centos使用key登录验证

    1. 新建用户lsyw 设置密码 #useradd lsyw #passwd lsyw 2. 测试新建用户可以登录 3. 修改root登录密码为通用root密码,测试用新密码登录是否成功 0!B2pj ...

  4. 解决使用IIS5.0配置的FTP服务器,客户端浏览器访问时无法获取目录列表的问题。

    我在windows xp sp3下利用iis构架了FTP服务器,允许且只允许匿名用户登陆.但刚开始配置好后,不管是使用命令行模式还是使用浏览器都发现无法访问. 于是怀疑防火墙屏蔽端口所致,果不其然,在 ...

  5. OpenSesame:一个能够攻击fixed-pin设备的工具

    OpenSesame是一种设备,这种设备可以通过无线技术来打开任何一个设有固定密码的车库门,我从中发现了一个攻击无线固定pin码设备的新方法. 演示视频以及详细信息: opensesame源代码:ht ...

  6. 如何调用super

    因此,决定是否调用 super,基于您打算如何重新实施方法: 如果打算补充超类实现的行为,请调用 super. 如果打算替换超类实现的行为,就不要调用 super. 如果您要补充超类行为,另一个需要重 ...

  7. 关于binary search的一点解惑

    在写binary search时对于mid的计算我最开始使用的是 mid = (low + high)/2; 后来看到在很多的实现为 mid = low + (high - low)/2; 想了一下两 ...

  8. 【Tsinghua OJ】多米诺骨牌(domino)问题

    (domino.c/cpp)[问题描述] 小牛牛对多米诺骨牌有很大兴趣,然而她的骨牌比较特别,只有黑色和白色的两种.她觉 得如果存在连续三个骨牌是同一种颜色,那么这个骨牌排列便是不美观的.现在她有n个 ...

  9. Swift:网络库Alamofire

    一,Alamofire的说明与配置 1,什么是Alamofire (1)Alamofire 的前身是 AFNetworking.AFNetworking 是 iOS 和 OS X 上很受欢迎的第三方H ...

  10. Ext.Net系列:一安装与使用

    http://www.cnblogs.com/howDo/archive/2011/04/27/2031084.html 下载地址:http://www.ext.net/download/ 示例地址: ...