Lua知識備忘錄


    最近對Lua很感興趣,以下是本階段學習的總結,包含三部分,一部分是基礎語法,一部分是擴展和解釋器嵌入,最后一部分是Lua小練習。

   知識涉及:Lua語言編程基礎;Lua&C++:Lua擴展、嵌入Lua解釋器、裸寫C++擴展、借助swig寫C++擴展。平台:Linux、gcc4.8.2

一、基礎語法

1、print("Hello World")

Lua中不需要分號,也不需要python那樣的嚴格格式;

單引號跟雙引號等價,多行文本使用兩個中括號擴起來:[[multi line]];

代碼中的注釋:--開頭的一行,或者是--[[ 多行注釋 --]];

Lua關鍵字:and break do else elseif end false for function if in local nil not or repeat return then true until while;

所有變量默認是全局變量,除非加上local 關鍵字;

支持多參數賦值:a, b = 1, 2;

Lua中的變量是對值的引用;

and和or都是short-cut-evaluation,a = 4 and 5, a是5; a = 4 or 5,a是4;

Lua不支持:switch-case、continue、i++、++i;

Lua將false、nil視為假,將其它視為真;

在Lua5.2之后,全局表為_ENV是一個table,這里包含了所有能使用的函數、類型、全局變量;

package.loaded 這也是個table,保存了所有加載的模塊,如果寫擴展(Lua腳本或者C模塊),可以通過修改_ENV表或者package.loaded來手動添加擴展模塊;

2、數據類型

(1)常用數據類型:number、string、table、function、bool、nil;
(2)不常用數據類型:userdata、thread;

注意:table也就是key--value鍵值對;function也是一種類型;thread也是一種類型,與協程相關;userdata用於表示自定義類型。

3、連接字符串

 a..b,變量a跟變量b的值連在一起,a和b是number或者string;

eg: 

a = 123  b = 'world' print(a..b)  --輸出:123world

4、table變量的定義

(1)a = {}   變量a指向空的table

(2)a = {1, "2"}    變量a指向 {1, "2"} table

(3)a = {} a["a"] = 1 a["x"] = 2    變量a指向空的table,接着通過a對這個table賦值

(4)a = {["x"] = 1, y = 2, [1] = "a"}    table構造的方式1

(5) a = {[{}] = "x", b = {}}   table構造的方式2

table可以作為數組,如上面的(2),也可以是map,如上面的(3)和(4)。

key可以是任何數據類型:number、string、table、function,value也可以是任何數據類型。
這也許就是動態類型帶來的極大隨意性吧。

5、table變量的使用

a[1] 或者是 a["b"],總之就是用map的方式去索引,table也用來表示數組(數組也只能用table表示),數組table的key為數字。

6、獲取數組的長度

(1)如果是純粹的數組(索引只有數字),則可以:#arrary、table.maxn(array),
#array只能獲取到連續的序號;
table.maxn(array)則是獲取到最大的序號;
如:a = {'a', 'b', [1000]='z'}
#a 輸出2
table.maxn(a) 輸出1000
 
(2)不純粹的數組
如果是包含有非數字序號的,則上述兩個方法都無法獲取到數組長度,唯一的方法是遍歷所有的元素
如:
function tablelength(T)
    local count =0
    for _ in pairs(T) do count = count +1 end return count end
可參考:

7、if--else語句

a = 1
if a == 1 then
    print("a is 1")
elseif a == 2 then
    print('a is 2')
end
-- 不等於號:~=

8、while語句

a = 1
while a ~= 5 do a = a + 1
 print(a) end

注意:沒有continue、i++

9、for語句

for語句有兩種使用方式:
(1) for 開始數字、終止數字、步長 do ...
for k = 1, 10, 2 do 
    print(k) 
end -- 輸出:1 3 5 7 9

(2) pair 和 ipair

a = {'a', 'b', 'c'}
for k, v in ipairs(a) do 
    print(k, v)
end  
--[[
輸出:
1    a
2    b
3    c
--]]

a = {b='b', a='a'}
for k, v in pairs(a) do 
    print(k, v)
end
--[[
輸出:
a   a
b   b
--]]

ipair只能用在數字為key的table上,且遍歷從1開始,直到對應key的value為nil,pair則沒有這個限制。

10、repeat語句

a = 1
repeat a = a + 1
 print(a) until a == 5

11、函數

function add(a, b)  return a + b end
function nothing(a, b)  return a, b end

括號不能隨便加,多個返回值再加上括號,就只返回一個:

print(nothing(1, 2)):   --輸出1 2
print((nothing(1, 2))):  -- 輸出1 

如果參數是一個table,則可以省略括號:

function add(a)
    return a.a + a.b
end

print(add({a = 1, b = 2}))  -- 3
print(add{a = 1, b = 2})  --3

支持可變參數:

function test1( ... )
    for i = 1, select('#', ...) do
        local arg = select(i, ...)
        print(arg)
   end
end


function test2( ... )-- 這種方式不推薦,會導致nil參數把參數列表截斷
     for i, v in ipairs{...} do
         print(v)
     end
end


test1('a', nil, 'c')
--[[
輸出:
a
nil
c
--]]

test2('a', nil, 'c') 
--[[
輸出:
a
--]]

 

12、閉包(closure)

閉包對於C++程序員來說是個新奇的概念(三年前我就覺得它很新奇),舉個栗子:

test = function(a)
    first = 2;  --這個變量可以被嵌套在test函數中的函數訪問,這個在Lua中也稱為upvalue
    return function(b) 
        tmp, first = first, b
        return tmp + b end
end

add = test();
print(add(2)); -- 4
print(add(3)); -- 5

閉包也是實現泛型for的原理(就是有個地方保存着變量),閉包還可以實現私有變量。 

15、require引入擴展庫

require('math') 
print(math.pi)

16、IO操作

--讀文件:
local file = assert(io.open('file_path', 'r')) for line in file:lines() do print(line)
end
file:close() --寫文件:
f_w = assert(io.open('file_path', 'w')) f_w:write('xxx') f_w:close()

17、table庫,可以對數組做各種操作

注意,是數組。
(1)數組元素連接:table.concat, : a = {"a", "b"} print(table.concat(a)) 輸出:ab
(2)數組元素插入: table.insert, : a = {"a", "b"} table.insert("c")
(3)數組元素最大序號:table.maxn, : a = {"a", "b", [100] = "z"} print(table.maxn(a))
(4)數組元素刪除:table.remove, : a = {"a", "b"} table.remove(a, 1): 刪除到序號為1的元素“a”
(5)數組元素排序:table.sort, :默認會根據元素的值從小到大排序,也可以自定義排序lambda函數:

a = {"b", "1", "z", "a"} 
table.sort(a, function(a, b) return a > b end)
print(table.concat(a))

18、string庫可以對數組做各種操作,有類正則表達式的功能

string.gfind string.gmatch string.gsub string.len

eg:

a = 'abc123'
b = string.match(a, '[a-z]([a-z])')
print(b)  --輸出:b

b = string.gmatch(a, '[a-z]')
for item in b do print(item) end  --輸出:a b c

local _, count = string.gsub(a, "[a-z]", "X")
print(_) -- 輸出:XXX123
print(count) --輸出:3

print(string.len(a)) --輸出:7

19、協同程序

    這是個有趣的功能,簡單說就是讓一個函數執行到一半就停下來去干別的,接着由於某些事件觸發它繼續往下走。控制者和被控制者在同一線程中執行,所以協程是單個線程上的設計,設計的初衷可能是為了在執行IO操作時交出控制權,之后再通過狀態切換/事件通知的方式讓程序繼續往下執行,減少CPU的空閑等待浪費。
lua上的demo:

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

    協程這個知識很多語言都有,甚至在Linux C++中,都有人為網絡服務實現了協程,做法是對阻塞的socket API做hook,調用這個函數時,應用程序切換去做其它事情,直到有通知觸發,才繼續從阻塞處往下執行。
擴展閱讀:http://www.udpwork.com/item/12045.html;騰訊開源的libco庫:http://code.tencent.com/libco.html

    協程的關鍵是,在執行耗時IO操作時,系統可以讓出控制權,讓用戶去干別的事情。這跟異步API很像,不同的是異步API的使用會要求有回調函數,所以我們實現一個功能的時候,會有異步API調用+回調函數,這樣就有兩部分代碼(當然,有些語言可以有lambda函數,這樣代碼就放在一塊了),而如果使用協程,代碼是可以放在一起的,好像在使用同步API寫代碼一樣(調用到關鍵API時會主動停下來,交出控制權,后面能拿到控制權繼續往下執行)。
擴展閱讀:http://blog.csdn.net/kobejayandy/article/details/11856735

    在Lua中,通過協程可以實現主程跟協程的數據交換:

在協程函數中有這樣的語句:a = coroutine.yield(xxx);在主程序中通過 coroutine.resume(co, yyy);  激活協程函數;主程序調用者,將得到xxx,而被調用者拿到的a是resume的參數yyy。所以,resume和yield配合:resume可以在主程序中將外部數據傳遞給協程內部;yield則將內部數據傳遞給主程序,eg:
function foo (a)
    for i=1, 10 do
        print('I get from outsite:'..coroutine.yield('I sent to outsite:'..(2 * a)))
    end
end

co = coroutine.create(foo)
print(coroutine.resume(co, 1))

--[[ 輸出:
I get from outsite:1
true    I sent to outsite:2
--]]

20、Lua的擴展模塊加載路徑

require('xxx'),可以加載xxx擴展模塊,如果require找不到Lua文件就會去找C程序庫,Lua文件跟C程序庫是兩種可能的Lua擴展方式。

在Lua解釋器中執行下面兩個語句:

print(package.path) --這是Lua腳本模塊可加載地址
print(package.cpath) --這是C程序庫可加載地址

Lua腳本模塊加載路徑格式舉例:.\?.lua;C:\Program Files (x86)\Lua\5.1\lua\?.lua;  其中?是通配符,表示任意名字。

Lua擴展C程序庫加載路徑格式舉例:.\?.dll;.\?51.dll; 如果在Linux下這是?.so.

在Linux下可以通過修改設置LUA_PATH、CLUA_PATH兩環境變量來設置對應的加載路徑,eg:

export LUA_PATH='/home/work/cswuyg/install/lua-lua/lib/md5/?.lua;./?.lua'
export LUA_CPATH='/home/work/cswuyg/install/lua-so/?.so;./?.so'

21、元表和元方法

對象可以指定元表,元表里包含有元方法,元方法可以做很多高級的事情。

print(xx.yy),如果xx變量沒有yy字段,那么就會去查找xx是否有元表,如果xx有元表,就去查xx的元表中是否有__index元方法,如果有元方法,就從元方法中獲取yy字段的值。

__index 元方法用於讀取,eg:
mt = {}  -- 元表
a = {}
setmetatable(a, mt)
mt.__index = {['x']=1}
print(a.x) 
-- 輸出:1
而__newindex用於賦值,例如:
mt = {}
mt.__newindex = {}
a = {}
setmetatable(a, mt)
a.x = 10
for k, v in pairs(mt.__newindex) do
print(k, v)
end
 --[[
輸出:
x       10
注意到,x並沒有保存在a中,而是保存在a的元表的__newindex字段所指向的table里。
--]]
如果想要不經過__index、也不想經過__newindex保存數據,那么可以采用原始的方法訪問:
rawget(table, index),
eg:
a = {['a'] = 'xx'}
print(rawget(a, 'a')) --輸出xx

使用元表.__index元方法設置元素的默認值

--設置table的默認值:
function set_defalut(table, value)
    local key = {}
    table[key] = value
    local mt = {__index = function(table) return table[key] end}
    setmetatable(table, mt)
end

table = {}
set_defalut(table, 100)
print(table.x) --輸出100

--當table中不存在x時,會去找__index字段保存的函數。
“重載”tostring元方法:
function to_string(a)
    local ret = ''
    for k, v in pairs(a) do
        ret = ret..k..':'..v..'\n'
    end
    return ret
end
 
function add_to_string(a)
mt = {__tostring=to_string}
setmetatable(a, mt)
end
 
table = {['a'] = 'a', ['b'] = 'b'}
add_to_string(table)
print(table)

--[[輸出:
a:a
b:b
--]]

 

22、點號跟冒號的區別

定義function的時候,如果使用冒號,那么默認會有self參數,self指向調用者自身;
調用function時,要采用冒號調用,如果采用點號調用,則要顯式的指明self。
A = {["b"]="b"}
function A:next(info)
    print(info, self.b)
end
 
function A:first(x)
    A:next("call from A:first")
end
 
A:first('x')
--[[
輸出:call from A:first       b
--]]

23、Lua匹配UTF8漢字

demo: head = string.match(line, '([%z\1-\127\194-\244][\128-\191]*).*')   

%z表示0,

%z\1-\127\194-\244][\128-\191]* 這是一個漢字的UTF8正則表示,

整個句子是用於獲取line的第一個漢字。

二、擴展&C++

1、使用Lua語言寫Lua擴展模塊,實現兩個數組的並集,並能序列化輸出

模塊的實現:mod.lua

module(..., package.seeall)

function union(t1, t2)
    local ret = {}
    for k, v in pairs(t1) do
        ret[v] = true
    end
    for k, v in pairs(t2) do
        ret[v] = true
    end
    mt = {__tostring=__tostring}
    setmetatable(ret, mt)

    return ret
end

function __tostring(t) 
    ret = ''
    for k, v in pairs(t) do
        ret = ret..k..'\n' 
    end
    return ret
end

模塊的使用 user.lua:

require('mod')

t1 = {'a', 'b'}
t2 = {'b', 'c'}

print(mod.union(t1, t2))

--[[
輸出:
a
b
c
----]]

 上面模塊的代碼,涉及到的知識:擴展模塊編寫、元表\元方法、table遍歷、字符串連接

2、嵌入Lua解釋器

Lua語言天生是為嵌入存在,嵌入也是很簡單的事情。

讓你的可執行程序能夠執行Lua腳本代碼,舉個栗子:

下載:首先要到官網下載Lua源碼:http://www.lua.org/download.html,我下載了最新的Lua-5.3.2版本。

編譯:如果Linux環境下出現錯誤:libreadline.so: undefined reference to `PC,需要修改、src/Makefile,增加-lncurses;可能還需要修改Makefile里的安裝目錄,裝到自己目錄下。

然后就可以開始寫測試代碼了:

makefile:

OBJ=test.o
CC=g++
CFLAGS=
ROOTDIR=./../
LUADIR=/home/users/cswuyg/install/lua/
LIBS=-llua -ldl

test: $(OBJ)
    $(CC) $(CFLAGS) -o test $(OBJ) -L$(LUADIR)lib $(LIBS)

test.o: test.cpp
    $(CC) $(CFLAGS) -c test.cpp -I$(LUADIR)include

test.cpp

/**
 * @file test.cpp
 * @author cswuyg
 * @date 2015/12/20 12:44:38
 * @brief 嵌入Lua解釋器
 *  
 **/
extern "C"
{
    #include "lua.h"
    #include "lualib.h"
    #include "lauxlib.h"
}
#include <iostream>
#include <string>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

//測試 luaL_dofile函數
void test_dofile(lua_State* L, const std::string& file_path) {
    luaL_dofile(L, "test.lua");
    std::string lua_ret = lua_tostring(L, 1);
    std::cout << "lua ret:" << lua_ret << std::endl;
}

//測試 luaL_dostring函數
void test_dostring(lua_State* L, const std::string& file_path) {
    std::ifstream ifs;    
    ifs.open(file_path.c_str());
    if (!ifs.is_open()) {
        return ;
    }
    std::stringstream buffer;
    buffer << ifs.rdbuf();
    std::string file_info(buffer.str());
    luaL_dostring(L, file_info.c_str());
    std::string lua_ret = lua_tostring(L, 1);
    std::cout << "lua ret:" << lua_ret << std::endl;
}

int main(int argc, char* argv[]) {
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);
    test_dostring(L, "test.lua");
    test_dofile(L, "test.lua");
    lua_close(L);
    return 0;
}

test.lua

function add(a, b)
    return a + b
end

c = add(10, 20)
return "10 + 20 is: "..c

從上面的test.cpp demo中可以看到關鍵函數:luaL_dostring 或者 luaL_dofile。

嵌入Lua解釋器之后產生的ELF文件,strip(Linux strip命令)之后只有204KB。

Lua解釋器的效率非常高,對於hello world類的demo,只需要200微秒(在我的機器上),而對應的采用V8解釋器執行js hello world需要2毫秒。

對於存在大量重復調用的demo代碼,上了LuaJIT性能可以提高幾倍(如果代碼不存在多次調用,JIT很難提高性能,除非是運行時的其它處理能達到代碼優化效果。測試了一次lua add函數調用,LuaJIT性能沒有提高)。以下是多次重復Lua函數調用測試代碼:

function add(a, b)
    return a + b 
end
 
for k = 1, 100000 do
c = add(10, k)
end
return "10 + 20 is: "..c       

Lua耗時:10700微秒;

LuaJIT耗時:617微秒;

LuaJIT對於熱點代碼能極大提高運行效率,因為這些熱點代碼被執行后,會被以機器碼的形式保存,后續的多次調用不需要再走轉換流程,直接執行機器碼,性能提高許多。

JIT結合了靜態編譯和動態解析的好處,在執行動態語言時,會將翻譯過的代碼以機器碼緩存起來,后續的使用就不需要再次翻譯,更多參考JIT知識:https://en.wikipedia.org/wiki/Just-in-time_compilation

如果要使用LuaJIT,源碼下載地址:http://luajit.org/download.html,我上面測試使用的是LuaJIT-2.0.4;使用方式跟非JIT Lua方式一致,使用JIT的ELF文件比非JIT的大200KB。

3、使用C++語言寫Lua擴展模塊

以下內容可能會比較碎,解決問題的方法不是不唯一的。

Lua調用C++函數,或者C++函數調用Lua,最重要的技術點就是兩種語言的‘溝通’,Lua的C++語言跟Lua語言數據交互是通過一個叫做Lua 狀態機(lua_State)的東西來做的,可以把它看作一個‘棧’。

我在練習寫擴展模塊的時候,基本按照這樣的層次來寫:實現層、包裝層、注冊層。這對業務功能做了划分,也對腳本語言層面的擴展做了划分,后續有新業務功能開發,或者新腳本語言擴展,已經有的業務功能實現不需要改動。

在用C++為Lua寫擴展時,有兩種使用方式,一種是提供一個so,Lua程序去require后使用,另一種是我寫的擴展類型可以跟Lua的內置類型一樣使用。我做了第二種實現的demo,如果要修改為使用so導出,只要增加一個生成so的makefile就可以。

C++寫擴展的demo代碼見github:自定義C++類加入Lua注:這個例子是將Lua解釋器嵌入到應用程序中,由我的應用程序去執行Lua腳本代碼。

至少有兩種方式可以將自定義函數/類型加入到全局表中,

方式1:

//把lib->func執行的結果作為lib->name的value保存到package.loaded 中      
luaL_requiref(L, lib->name, lib->func, 1); 
//清空狀態機L
lua_settop(L, 0);

方式2:

lib->func(L);//執行注冊,L棧頂是注冊了函數的table             
lua_setglobal(L, lib->name);  //把棧頂的table作為value,以lib->name 作為key保存到全局表中。

詳細代碼見這里

這兩種方式可以實現把導出函數table放到全局表/已加載包中,使用者直接 {require("name")},就可以使用 name.xxx,而不需要 {name = require("name")};用起來跟文章上邊的mod.lua 模塊一樣。
如果不是直接把table放到全局table或者包加載table中,那就是這樣子寫: lua-socket.c,只使用luaL_newlib API把函數table設置到狀態機的棧頂。

在編寫Lua擴展時,如果有需要在擴展模塊中保存數據狀態,可以使用1、全局數據狀態,關鍵字:LUA_REGISTRYINDEX;2、模塊環境,關鍵字:LUA_ENVIRONINDEX;3、閉包函數,關鍵字:lua_pushcclosure;學習資料:http://www.cnblogs.com/stephen-liu74/archive/2012/07/25/2470025.html

4、借助swig框架實現Lua擴展模塊

swig:http://nchc.dl.sourceforge.net/project/swig/swig/swig-3.0.7/swig-3.0.7.tar.gz,下載之后配置--prefix,做編譯安裝即可。

文檔:http://www.swig.org/Doc2.0/Lua.html

以下為demo,由兩部分組成:我們的實現代碼;xxx.i文件,用於給swig生成框架。

my_module.i (生成wrapper文檔命令行:swig -c++ -lua my_module.i)

%module my_module 
%include "std_string.i" 
%{
#include "my_module.h"
%}
%include "my_module.h"

注意到上面的std_string.i,必須有它才能導出std::string類型,更多的其它類型在這里swig的github

my_module.h

/**
 * @file my_module.h
 * @author cswuyg
 * @date 2015/12/20 18:05:05
 * @brief 我的測試模塊
 *  
 **/
#ifndef  __MY_MODULE_H_
#define  __MY_MODULE_H_

#include <string>

int add(int a, int b);

class Hello {
public:
    std::string get_info();
    bool set_test(Hello* p);
    Hello* get_test();
private:
    Hello* _test_p;
};


#endif  //__MY_MODULE_H_

/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */

test.lua

a = my_module.Hello()
b = my_module.Hello()
a:set_test(b);
c = a:get_test();
print(c:get_info());

print(my_module.add(1, 2))

完整代碼見github:利用swig做封裝注:這個例子是將Lua解釋器嵌入到應用程序中,由我的應用程序去執行Lua腳本代碼。

使用swig框架可以讓開發者把精力放在業務層面,省力不少,除了swig,還有Luabind、LuaPlus...等一堆框架/工具。我選擇swig做,是因為swig也支持Python、JavaScript...

三、Lua練手

1、遍歷成語詞典,獲取某個字開頭的成語,用到了MongoDB第三方lua驅動,它的代碼很簡短,文章最后有介紹。

--[[
生成某個字開頭的所有成語
cswuyg 2015.12.1
思路:
1、先在外面把成語詞典轉換為UTF8格式;
2、使用正則表達式剔除非四字成語;
3、使用正則找出四字成語的首字
----]]
require('math')
mongo = require "mongo"

client = mongo.client{ host = 'xxxx host', port='27017' }
insert_to_mongo = function(t) --這里是單條寫入,批量寫入會快點,但mongo驅動在批量寫入時有core,暫不使用批量
    client.idioms_solitaire_dataxx.head:insert(t)
    local r = client:runCommand('getLastError', 1, 'w', 1)
end

-- 操作控制
idioms_ctrl = {
    idioms_path = nil , -- 成語詞典路徑
    idioms = {}, -- 內存成語詞典
    idioms_len = 0, -- 成語詞典長度
    head_table = {}
}

--建立head 詞典
function idioms_ctrl:build_head_dict()
    self.head_table = {}
    for k, v in ipairs(self.idioms) do
        head = string.match(v, '([%z\1-\127\194-\244][\128-\191]*).*')
        if self.head_table[head] then 
            table.insert(self.head_table[head], v)
        else
            self.head_table[head] = {v}
        end
    end
end

-- 加載字典到idioms中,並創建head_dict
function idioms_ctrl:load_dict()
    local file = assert(io.open(self.idioms_path, 'r'))
    for line in file:lines() do
        local idiom = {}
        local_, count = string.gsub(line, "[^\128-\193]", "")  --統計有多少漢字
        if count == 4 then --只保留4字成語
            for uchar in string.gmatch(line, "[%z\1-\127\194-\244][\128-\191]*") do 
                table.insert(idiom, uchar)
            end
            item = table.concat(idiom)
            if string.len(item) > 0 then
                table.insert(self.idioms, table.concat(idiom))
                self.idioms_len = self.idioms_len + 1
            end
        end
    end
    idioms_ctrl:build_head_dict()
end

-- 寫到mongodb和文件
function idioms_ctrl:write_all_head()
    self.f_w = assert(io.open(self.result_path, 'w'))
    for head, idioms in pairs(self.head_table) do
        idioms_ctrl:write_result(head, idioms)
    end
end

-- 寫入結果到結果文件
function idioms_ctrl:write_result(head, list)
    self.f_w:write(head..':'..table.concat(list, ',')..'  len:'..#list..'\n')
    info = table.concat(list, ',')
    xx = {['_id']=head, ['data']=info, ['len']=#list}
    insert_to_mongo(xx)
    return false
end

-- 全部跑
function run(idioms_dict_path, result_path)
    print('dict :'..idioms_dict_path)
    idioms_ctrl.result_path = result_path
    idioms_ctrl.idioms_path = idioms_dict_path
    idioms_ctrl:load_dict()
    idioms_ctrl:write_all_head()
end

-- 主函數
function main() 
    math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) )

    local s = os.clock()
    if not arg[1] or not arg[2] then
        print('input format: lua xx.lua [idioms_dict_path] [result_path]')
        return false
    end
    print('arg[1]:'..arg[1])
    print('arg[2]:'..arg[2])
    run(arg[1], arg[2])
    local e = os.clock()
    print('cost second:'..e-s)
end

main()

 

補充:

1、Lua5.1版本的string.gfind,在5.2版本中更換為string.gmatch.

2、luaL_register函數可以將C函數注冊到Lua語言環境的package.loaded中,這個函數在Lua5.2中被廢棄,不再支持直接注冊到全局表中,一般更換為使用:luaL_newlib,將函數注冊到堆棧頂的table,然后再另行處理(如使用lua_setglobal)。

3、Lua的MD5庫,到github上找一個,然后設置到LUA_PATH上即可,用過的MD5庫:https://github.com/kikito/md5.lua

后續工作重點已經不在Lua上,但會不定期更新。

 

本文所在:http://www.cnblogs.com/cswuyg/p/5049935.html 

 

學習資料推薦:

1、《Lua程序設計》

2、http://www.jellythink.com/archives/category/language/lua

3、http://www.lua.org/manual/5.2/manual.html 

4、雲風的MongoDB Lua驅動,代碼精致可讀:https://github.com/cloudwu/lua-mongo/,編譯時需要Lua5.2版本,可能需要修改makefile文件

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM