一、lua中的標識符能夠是由任意字母、數字和下劃線構成的字符串,但不能以數字開頭。
二、lua將一般相似"_VALUE"的標識符做爲保留標識符
三、lua的保留字
and break do else elseif
end false for function if
in loacl nil not or
repear return then true until
while
有大小寫之分java
四、行註釋--
塊註釋--[[ …… ]]
==============================================================
全局變量
lua中訪問一個未初始化的變量不會引起錯誤,結果是一個nil。
若是要刪除某個全局變量的話置其爲nil
==============================================================c++
**************************************************************
二、類型與值
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或函數等)同樣
都是自動內存管理機制所管理的對象。windows
能夠用[[ …… ]]來界定一個字母字符串
eg:page=[[
i like lua
i like c++
i like java
]]
若是第一個字符是換行字符,那麼lua會忽略它。數組
數字與字符串自動轉換,lua會嘗試將該字符串轉換成數字
可是最好不要依賴
----------------安全
..是字符串鏈接操做符網絡
若是須要顯示地將一個字符串轉換成數字,可用tonumber,當不能正確
表示時返回nil數據結構
若要轉換成字符串,能夠調用tostring或者與空字符串鏈接。多線程
在lua5.1中,能夠在字符串前放置操做符「#」來獲取改字符串的長度
五、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)獲取
六、function
在lua中,函數是做爲"第一類值"來看待的。
這表示函數能夠存儲在變量中,能夠經過參數傳遞給其餘函數
還能夠做爲其餘函數的返回值。
七、uerdata(自定義類型)和thread(線程)
userdata用於表示一種由應用程序或C語言庫所建立的新類型。
*************************************************************
三、表達式
一、算術操做符
+、-、*、/、^、%、-(負號)
二、關係操做符
<、 >、 <=、 >=、 ==、 ~=
對於table、userdata以及函數,lua是做引用比較的。
三、邏輯操做符
and or not
對於and,若是第一個操做數爲假,就返回第一個操做數
不然返回第二個操做數。[即哪一個假返回哪一個除非都是真則返回第二個]
對於or,若是第一個操做數爲真,就返回第一個操做數,不然返回
第二個操做數[即哪一個真返回哪一個除非都是假則返回第二個]
and的優先級高於or
4
字符串的鏈接 ..
五、優先級
^
not # -
* / %
+ -
..
< > <= >= -= ==
and
or
六、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"}
*********************************************************
四、語句
一、
lua容許多重賦值,即對對多個值賦予多個變量
即 a,b = 10, 2*x
二、
j=10 --全局變量
loacl i=1 --局部變量
在交互模式中,每行輸入內容自身就造成了一個程序塊。
若是一條聲明語句沒有初始化賦值,那麼它聲明的全部bianliang都會被初始化爲nil
三、
一、if then else \ elseif
二、while value do ... end
三、repeat .... until ... 爲真的時候結束
四、在lua中,一個聲明在循環體中的局部變量的做用域包括了條件測試
這是5.1的新功能。
五、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章 函數***********************
一、
全部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開始返回該數組的全部元素,重要用途用於"泛型調用"機制中。
二、變長參數
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個形參
三、具名實參
*******************第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 排序 ??
一、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
二、非全局的函數
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
三、尾調用
當一個函數調用時另一個函數的最後一個動做時,該調用纔算是一條尾調用。
eg:fucntion f(x) return g(x) end
g(x)執行完可以返回到調用f的點上,即拋棄f
一條「尾調用」就比如是一條goto語句。
在lua中的應用就是編寫狀態機
尾調用消除能夠防止棧溢出。
******************第7章 迭代器與泛型for**************************
一、
每個迭代器都須要在每次成功調用之間保持一些狀態,這樣才能知道它所在的位置以及如何進到下一個位置。
closure對於這類任務提供了極佳的支持。
二、泛型for
泛型for在循環過程內部保存了迭代器函數
實際上它保存着3個值
一個迭代器函數、一個恆定狀態和一個控制變量
for <var-list> in <exp-list> do
<body>
end
<exp-list>一般只有一個元素,即一個對迭代器工廠的調用
for所作的第一件事情就是對in後面的表達式求值。這些表達式應該
返回3個值供for保存:迭代器函數、恆定狀態和控制變量的初值
相似多重賦值...以後 for會以恆定狀態和控制變量來調用迭代器函數
三、無狀態的迭代器
就是自身不保存任何狀態的迭代器。
所以能夠在多個循環中使用同一個無狀態的迭代器,
避免建立新的closure開銷。
典型例子就是 ipairs
八、具備複雜形態的迭代器
一般,迭代器須要保存許多狀態,
可是泛型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之間交換數據時有兩個問題:
一、動態類型與靜態類型區別
二、自動內存管理與手動內存管理區別
-----------------------------------------------------------------
聯合數據類型(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不支持共享內存的搶先式多線程。
一、ANSI C沒有提供這樣的功能。
二、不是一個好的選擇
....
搶先式的線程和共享的內存 會有些沒法預料的問題..好比..
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