• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            麒麟子

            ~~

            導航

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統計

            常用鏈接

            留言簿(12)

            隨筆分類

            隨筆檔案

            Friends

            WebSites

            積分與排名

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            [轉]通過例子學習Lua

            據說本文作者是OGDEV的HACK達人

            通過例子學習Lua(1) ---- Hello World

            1.前言
            游戲中少不了用到腳本語言. Lua是一種和C/C++結合非常緊密的腳本語言,效率極高。
            一般是對時間要求比較高的地方用C++寫,而經常需要改動的地方用Lua寫。

            偶最近在學習Lua, 所以寫出心得和大家共享. Lua是一種完全免費的腳本語言,
            它的官方網站在http://www.lua.org.在網站上可以下載到lua的源碼, 沒有可
            執行版本, 不過不用擔心, 因為lua源碼可以在任何一種C/C++的編譯器上編譯.

            如果要學習Lua, 官方網站上的Reference是必備的,上面有每個命令的用法,非常詳
            細。
            參考手冊 http://www.lua.org/manual/5.0/
            作者寫的Programming in Lua http://www.lua.org/pil/

            2.編譯
            如果用的VC, 可以下載所需的project文件,地址在
            http://sourceforge.net/project/showfiles.php?group_id=32250&package_id=115604
            偶用的是cygwin和linux, 打入以下命令即可,
            tar -zxvf lua-5.0.2.tar.gz
            cd lua-5.0.2
            sh ./configure
            make
            這樣就OK了。
            為了以后使用方便,最好把bin目錄加入到path里面。

            3."Hello, world!"
            現在開始偶們的第一個小程序"Hello, world!"
            把以下程序打入文件e01.lua

            例1:e01.lua
            -- Hello World in Lua
            print("Hello World.")

            Lua有兩種執行方式,一種是嵌入到C程序中執行,還有一種是直接從命令行方式下執
            行。
            這里為了調試方便,采用第二種方式,執行命令 lua e01.lua

            輸出結果應該是:
            Hello World.

            4.程序說明
            第一行 -- Hello World in Lua
            這句是注釋,其中--和C++中的//意思是一樣的
            第二行 print("Hello World.")
            調用lua內部命令print,輸出"Hello World."字符串到屏幕,Lua中的字符串全部是
            由"括起來的。
            這個命令是一個函數的調用,print是lua的一個函數,而"Hello World."是print的參
            數。

            5.試試看
            在Lua中有不少字符串的處理操作,本次的課后試試看的內容就是,找出連接兩個字符串
            的操作,
            并且print出來。
            --

            通過例子學習Lua(2) --- Lua基礎

            1. 函數的使用
            以下程序演示了如何在Lua中使用函數, 及局部變量
            例e02.lua
            -- functions
            function pythagorean(a, b)   
                   local c2 = a^2 + b^2   
                   return sqrt(c2)
            end
            print(pythagorean(3,4))

            運行結果
            5

            程序說明
            在Lua中函數的定義格式為:
            function 函數名(參數)
                   ...
            end
            與Pascal語言不同, end不需要與begin配對, 只需要在函數結束后打個end就可以了.
            本例函數的作用是已知直角三角形直角邊, 求斜邊長度. 參數a,b分別表示直角邊長,
            在函數內定義了local形變量用于存儲斜邊的平方. 與C語言相同, 定義在函數內的代
            碼不會被直接執行, 只有主程序調用時才會被執行.
            local表示定義一個局部變量, 如果不加local剛表示c2為一個全局變量, local的作用域
            是在最里層的end和其配對的關鍵字之間, 如if ... end, while ... end等。全局變量

            作用域是整個程序。

            2. 循環語句
            例e03.lua
            -- Loops
            for i=1,5 do   
                   print("i is now " .. i)
            end

            運行結果
            i is now 1
            i is now 2
            i is now 3
            i is now 4
            i is now 5

            程序說明
            這里偶們用到了for語句
            for 變量 = 參數1, 參數2, 參數3 do
                   循環體
            end
            變量將以參數3為步長, 由參數1變化到參數2
            例如:   
            for i=1,f(x) do print(i) end
            for i=10,1,-1 do print(i) end

            這里print("i is now " .. i)中,偶們用到了..,這是用來連接兩個字符串的,
            偶在(1)的試試看中提到的,不知道你們答對了沒有。
            雖然這里i是一個整型量,Lua在處理的時候會自動轉成字符串型,不需偶們費心。

            3. 條件分支語句
            例e04.lua
            -- Loops and conditionals
            for i=1,5 do
                   print(“i is now “ .. i)
                     if i < 2 then       
                           print(“small”)   
                     elseif i < 4 then       
                           print(“medium”)   
                     else       
                           print(“big”)   
                     end
            end

            運行結果
            i is now 1
            small
            i is now 2
            medium
            i is now 3
            medium
            i is now 4
            big
            i is now 5
            big

            程序說明
            if else用法比較簡單, 類似于C語言, 不過此處需要注意的是整個if只需要一個end,
            哪怕用了多個elseif, 也是一個end.
            例如
                if op == "+" then
                  r = a + b
                elseif op == "-" then
                  r = a - b
                elseif op == "*" then
                  r = a*b
                elseif op == "/" then
                  r = a/b
                else
                  error("invalid operation")
                end


            4.試試看
            Lua中除了for循環以外, 還支持多種循環, 請用while...do和repeat...until改寫本文
            中的for程序

            --
            通過例子學習Lua(3) ---- 數據結構

            1.簡介
            Lua語言只有一種基本數據結構, 那就是table, 所有其他數據結構如數組啦,
            類啦, 都可以由table實現.

            2.table的下標
            例e05.lua
            -- Arrays
            myData = {}
            myData[0] = “foo”
            myData[1] = 42

            -- Hash tables
            myData[“bar”] = “baz”

            -- Iterate through the
            -- structure
            for key, value in myData do
            print(key .. “=“ .. value)
            end

            輸出結果
            0=foo
            1=42
            bar=baz

            程序說明
            首先定義了一個table myData={}, 然后用數字作為下標賦了兩個值給它. 這種
            定義方法類似于C中的數組, 但與數組不同的是, 每個數組元素不需要為相同類型,
            就像本例中一個為整型, 一個為字符串.

            程序第二部分, 以字符串做為下標, 又向table內增加了一個元素. 這種table非常
            像STL里面的map. table下標可以為Lua所支持的任意基本類型, 除了nil值以外.

            Lua對Table占用內存的處理是自動的, 如下面這段代碼
            a = {}
            a["x"] = 10
            b = a -- `b' refers to the same table as `a'
            print(b["x"]) --> 10
            b["x"] = 20
            print(a["x"]) --> 20
            a = nil -- now only `b' still refers to the table
            b = nil -- now there are no references left to the table
            b和a都指向相同的table, 只占用一塊內存, 當執行到a = nil時, b仍然指向table,
            而當執行到b=nil時, 因為沒有指向table的變量了, 所以Lua會自動釋放table所占內存

            3.Table的嵌套
            Table的使用還可以嵌套,如下例
            例e06.lua
            -- Table ‘constructor’
            myPolygon = {
            color=“blue”,
            thickness=2,
            npoints=4;
            {x=0, y=0},
            {x=-10, y=0},
            {x=-5, y=4},
            {x=0, y=4}
            }

            -- Print the color
            print(myPolygon[“color”])

            -- Print it again using dot
            -- notation
            print(myPolygon.color)

            -- The points are accessible
            -- in myPolygon[1] to myPolygon[4]

            -- Print the second point’s x
            -- coordinate
            print(myPolygon[2].x)

            程序說明
            首先建立一個table, 與上一例不同的是,在table的constructor里面有{x=0,y=0},
            這是什么意思呢? 這其實就是一個小table, 定義在了大table之內, 小table的
            table名省略了.
            最后一行myPolygon[2].x,就是大table里面小table的訪問方式.

            --
            通過例子學習Lua(4) -- 函數的調用

            1.不定參數
            例e07.lua
            -- Functions can take a
            -- variable number of
            -- arguments.
            function funky_print (...)
            for i=1, arg.n do
            print("FuNkY: " .. arg)
            end
            end

            funky_print("one", "two")

            運行結果
            FuNkY: one
            FuNkY: two

            程序說明
            * 如果以...為參數, 則表示參數的數量不定.
            * 參數將會自動存儲到一個叫arg的table中.
            * arg.n中存放參數的個數. arg[]加下標就可以遍歷所有的參數.


            2.以table做為參數
            例e08.lua
            -- Functions with table
            -- parameters
            function print_contents(t)
            for k,v in t do
            print(k .. "=" .. v)
            end
            end
            print_contents{x=10, y=20}

            運行結果
            x=10
            y=20

            程序說明
            * print_contents{x=10, y=20}這句參數沒加圓括號, 因為以單個table為參數的時候,
            不需要加圓括號
            * for k,v in t do 這個語句是對table中的所有值遍歷, k中存放名稱, v中存放值


            3.把Lua變成類似XML的數據描述語言
            例e09.lua
            function contact(t)
            -- add the contact ‘t’, which is
            -- stored as a table, to a database
            end

            contact {
            name = "Game Developer",
            email = "hack@ogdev.net",
            url = "http://www.ogdev.net,
            quote = [[
            There are
            10 types of people
            who can understand binary.]]
            }

            contact {
            -- some other contact
            }

            程序說明
            * 把function和table結合, 可以使Lua成為一種類似XML的數據描述語言
            * e09中contact{...}, 是一種函數的調用方法, 不要弄混了
            * [[...]]是表示多行字符串的方法
            * 當使用C API時此種方式的優勢更明顯, 其中contact{..}部分可以另外存成一配置文


            4.試試看
            想想看哪些地方可以用到例e09中提到的配置方法呢?

            --

            通過例子學習Lua(5) ---- Lua與C交互入門

            1.簡介

            Lua與C/C++結合是很緊密的, Lua與C++交互是建立在Lua與C的基礎上的, 所
            以偶先從Lua與C講起.

            正如第一講所說, 運行Lua程序或者說調用Lua主要有兩種方式:
            * 通過命令行執行"Lua"命令
            * 通過Lua的C庫
            雖然此前偶們一直用第一種方式, 但偶要告訴你, 通過Lua的C庫執行才是游戲中
            常用的方式.

            2.Lua的C庫

            Lua的C庫可以做為Shared Library調用, 但一般開發游戲時會把Lua的所有源程序
            都包含在內, 并不把Lua編譯成共享庫的形式. 因為Lua程序只有100多K, 而且幾乎
            可以在任何編譯器下Clean Compile. 帶Lua源程序的另一個好處時, 可以隨時對Lua
            本身進行擴充, 增加偶們所需的功能.

            Lua的C庫提供一系列API:
            * 管理全局變量
            * 管理tables
            * 調用函數
            * 定義新函數, 這也可以完全由C實現
            * 垃圾收集器Garbage collector, 雖然Lua可以自動進行, 但往往不是立即執行的,
            所以對實時性要求比較高的程序, 會自己調用垃圾收集器
            * 載入并執行Lua程序, 這也可以由Lua自身實現
            * 任何Lua可以實現的功能, 都可以通過Lua的C API實現, 這對于優化程序的運行速度
            有幫助. 經常調用的共用的Lua程序片斷可以轉成C程序, 以提高效率. 連Lua都是C寫的
            還有什么C不能實現呢?

            3.Lua與C集成的例子
            例e10.c
            /* A simple Lua interpreter. */
            #include <stdio.h>
            #include <lua.h>
            int main(int argc, char *argv[]) {
            char line[BUFSIZ];
            lua_State *L = lua_open(0);
            while (fgets(line, sizeof(line), stdin) != 0)
            lua_dostring(L, line);
            lua_close(L);
            return 0;
            }

            編譯
            Linux/Cygwin
            * 先編譯Lua, 并把頭文件放入include路徑
            * gcc e10.c -llua -llualib -o e10

            VC6/VC2003
            * 先編譯Lua, 在Option中設置頭文件和庫文件路徑
            * 新建工程,在工程配置中加入附加庫lua.lib和lualib.lib
            * 編譯成exe

            運行結果
            本程序的功能是實現一個Lua解釋器, 輸入的每行字符都會被解釋成Lua并執行.

            程序說明
            * #include <lua.h> 包含lua頭文件, 然后才可以使用API
            * lua_State *L = lua_open(0) 打開一個Lua執行器
            * fgets(line, sizeof(line), stdin) 從標準輸入里讀入一行
            * lua_dostring(L, line) 執行此行
            * lua_close(L) 關閉Lua執行器


            例e11.c
            /* Another simple Lua interpreter. */
            #include <stdio.h>
            #include <lua.h>
            #include <lualib.h>
            int main(int argc, char *argv[]) {
            char line[BUFSIZ];
            lua_State *L = lua_open(0);
            lua_baselibopen(L);
            lua_iolibopen(L);
            lua_strlibopen(L);
            lua_mathlibopen(L);
            while (fgets(line, sizeof(line), stdin) != 0)
            lua_dostring(L, line);
            lua_close(L);
            return 0;
            }

            運行結果
            本程序的功能是實現一個Lua解釋器, 輸入的每行字符都會被解釋成Lua并執行.
            與上例不同的是, 本例調用了Lua的一些標準庫.

            程序說明
            * #include <lualib.h> 包含Lua的標準庫
            * 以下這幾行是用來讀入Lua的一些庫, 這樣偶們的Lua程序就可以有更多的功能.
            lua_baselibopen(L);
            lua_iolibopen(L);
            lua_strlibopen(L);
            lua_mathlibopen(L);

            4.試試看
            把上面兩個小例子在你熟悉的編譯器中編譯執行, 并試試能否與Lua源碼樹一起編譯

            --
            通過例子學習Lua(6) ---- C/C++中用Lua函數

            參考英文文檔http://tonyandpaige.com/tutorials/lua2.html

            1.簡介
            偶們這次主要說說怎么由Lua定義函數, 然后在C或者C++中調用. 這里偶們
            暫不涉及C++的對象問題, 只討論調用函數的參數, 返回值和全局變量的使用.

            2.
            這里偶們在e12.lua里先定義一個簡單的add(), x,y為加法的兩個參數,
            return 直接返回相加后的結果.

            例e12.lua
            -- add two numbers
            function add ( x, y )
            return x + y
            end

            在前一次里, 偶們說到 lua_dofile() 可以直接在C中執行lua文件. 因為偶們
            這個程序里只定義了一個add()函數, 所以程序執行后并不直接結果, 效果相當
            于在C中定義了一個函數一樣.

            Lua的函數可以有多個參數, 也可以有多個返回值, 這都是由棧(stack)實現的.
            需要調用一個函數時, 就把這個函數壓入棧, 然后順序壓入所有參數, 然后用
            lua_call()調用這個函數. 函數返回后, 返回值也是存放在棧中. 這個過程和
            匯編執行函數調用的過程是一樣的.

            例e13.cpp 是一個調用上面的Lua函數的例子
            #include <stdio.h>

            extern "C" { // 這是個C++程序, 所以要extern "C",
            // 因為lua的頭文件都是C格式的
            #include "lua.h"
            #include "lualib.h"
            #include "lauxlib.h"
            }

            /* the Lua interpreter */
            lua_State* L;

            int luaadd ( int x, int y )
            {
            int sum;

            /* the function name */
            lua_getglobal(L, "add");

            /* the first argument */
            lua_pushnumber(L, x);

            /* the second argument */
            lua_pushnumber(L, y);

            /* call the function with 2
            arguments, return 1 result */
            lua_call(L, 2, 1);

            /* get the result */
            sum = (int)lua_tonumber(L, -1);
            lua_pop(L, 1);

            return sum;
            }

            int main ( int argc, char *argv[] )
            {
            int sum;

            /* initialize Lua */
            L = lua_open();

            /* load Lua base libraries */
            lua_baselibopen(L);

            /* load the script */
            lua_dofile(L, "e12.lua");

            /* call the add function */
            sum = luaadd( 10, 15 );

            /* print the result */
            printf( "The sum is %d\n", sum );

            /* cleanup Lua */
            lua_close(L);

            return 0;
            }

            程序說明:
            main中過程偶們上次已經說過了, 所以這次只說說luaadd的過程
            * 首先用lua_getglobal()把add函數壓棧
            * 然后用lua_pushnumber()依次把x,y壓棧
            * 然后調用lua_call(), 并且告訴程序偶們有兩個參數一個返回值
            * 接著偶們從棧頂取回返回值, 用lua_tonumber()
            * 最后偶們用lua_pop()把返回值清掉

            運行結果:
            The sum is 25

            編譯方法
            Linux下把程序存成e13.cpp
            g++ e13.cpp -llua -llualib -o e13
            ./e13

            VC下編譯方法
            * 首先建立一個空的Win32 Console Application Project
            * 把e13.cpp加入工程中
            * 點project setting,然后設置link選項, 再加上lua.lib lualib.lib兩個額外的庫
            * 最后編譯

            建立好的project可以在這里下載
            VC http://tonyandpaige.com/tutorials/luaadd.zip
            Linux http://tonyandpaige.com/tutorials/luaadd.tar.gz

            3.全局變量
            上面偶們用到了lua_getglobal()但并沒有詳細講, 這里偶們再舉兩個小例子來說下全局
            變量
            lua_getglobal()的作用就是把lua中全局變量的值壓入棧
            lua_getglobal(L, "z");
            z = (int)lua_tonumber(L, 1);
            lua_pop(L, 1);
            假設Lua程序中定義了一個全局變量z, 這段小程序就是把z的值取出放入C的變量z中.

            另外Lua中還有一個對應的函數lua_setglobal(), 作用是用棧頂的值填充指定的全局變

            lua_pushnumber(L, 10);
            lua_setglobal(L, "z");
            例如這段小程序就是把lua中的全局變量z設為10, 如果lua中未定義z的話, 就會自動創
            建一個
            全局變量z并設為10.

            4.試試看
            自己寫個函數用C/C++來調用下試試

            --
            通過例子學習Lua(7) ---- Lua中調用C/C++函數

            1.前言
            上次偶說到從C/C++中調用Lua的函數, 然后就有朋友問從Lua中如何調用C/C++的
            函數, 所以偶們這次就來說說這個問題. 首先偶們會在C++中建立一個函數, 然后
            告知Lua有這個函數, 最后再執行它. 另外, 由于函數不是在Lua中定義的, 所以
            無法確定函數的正確性, 可能在調用過程中會出錯, 因此偶們還會說說Lua出錯處
            理的問題.

            2.Lua中調用C函數
            在lua中是以函數指針的形式調用函數, 并且所有的函數指針都必須滿足如下此種
            類型:
            typedef int (*lua_CFunction) (lua_State *L);

            也就是說, 偶們在C++中定義函數時必須以lua_State為參數, 以int為返回值才能
            被Lua所調用. 但是不要忘記了, 偶們的lua_State是支持棧的, 所以通過棧可以
            傳遞無窮個參數, 大小只受內存大小限制. 而返回的int值也只是指返回值的個數
            真正的返回值都存儲在lua_State的棧中. 偶們通常的做法是做一個wrapper, 把
            所有需要調用的函數都wrap一下, 這樣就可以調用任意的函數了.

            下面這個例子是一個C++的average()函數, 它將展示如何用多個參數并返回多個值

            例e14.cpp
            #include <stdio.h>

            extern "C" {
            #include "lua.h"
            #include "lualib.h"
            #include "lauxlib.h"
            }

            /* the Lua interpreter */
            lua_State* L;

            static int average(lua_State *L)
            {
            /* get number of arguments */
            int n = lua_gettop(L);
            double sum = 0;
            int i;

            /* loop through each argument */
            for (i = 1; i <= n; i++)
            {
            /* total the arguments */
            sum += lua_tonumber(L, i);
            }

            /* push the average */
            lua_pushnumber(L, sum / n);

            /* push the sum */
            lua_pushnumber(L, sum);

            /* return the number of results */
            return 2;
            }

            int main ( int argc, char *argv[] )
            {
            /* initialize Lua */
            L = lua_open();

            /* load Lua base libraries */
            lua_baselibopen(L);

            /* register our function */
            lua_register(L, "average", average);

            /* run the script */
            lua_dofile(L, "e15.lua");

            /* cleanup Lua */
            lua_close(L);

            return 0;
            }

            例e15.lua
            -- call a C++ function

            avg, sum = average(10, 20, 30, 40, 50)

            print("The average is ", avg)
            print("The sum is ", sum)


            程序說明:
            * lua_gettop()的作用是返回棧頂元素的序號. 由于Lua的棧是從1開始編號的,
            所以棧頂元素的序號也相當于棧中的元素個數. 在這里, 棧中元素的個數就
            是傳入的參數個數.
            * for循環計算所有傳入參數的總和. 這里用到了數值轉換lua_tonumber().
            * 然后偶們用lua_pushnumber()把平均值和總和push到棧中.
            * 最后, 偶們返回2, 表示有兩個返回值.
            * 偶們雖然在C++中定義了average()函數, 但偶們的Lua程序并不知道, 所以需
            要在main函數中加入

            /* register our function */
            lua_register(L, "average", average);

            這兩行的作用就是告訴e15.lua有average()這樣一個函數.
            * 這個程序可以存成cpp也可以存成c, 如果以.c為擴展名就不需要加extern "C"

            編譯的方法偶們上次說過了, 方法相同.
            e15.lua執行的方法只能用上例中的C++中執行, 而不能用命令行方式執行.

            3.錯誤處理
            在上例中, 偶們沒有對傳入的參數是否為數字進行檢測, 這樣做不好. 所以這里偶
            們再加上錯誤處理的片斷.

            把這段加在for循環之內:
            if (!lua_isnumber(L, i)) {
            lua_pushstring(L, "Incorrect argument to 'average'");
            lua_error(L);
            }
            這段的作用就是檢測傳入的是否為數字.

            加上這段之后, 偶們debug的時候就會簡單許多. 對于結合兩種語言的編程, 它們之
            間傳遞數據的正確性檢測是非常重要的.

            這里有別人寫好的例子:
            VC的 http://tonyandpaige.com/tutorials/luaavg.zip
            Linux的 http://tonyandpaige.com/tutorials/luaavg.tar.gz

            至此, Lua與C的結合就基本講完了, 下次偶要開始說說Lua與面向對象.
            但是偶自己還沒有學完, 所以大家可能要多等兩天了. Sorry!

            --

            posted on 2009-05-16 21:37 麒麟子 閱讀(4014) 評論(1)  編輯 收藏 引用 所屬分類: Programming

            評論

            # re: [轉]通過例子學習Lua 2015-07-27 15:36 效益

            按時  回復  更多評論   

            欧美久久亚洲精品| 久久人妻少妇嫩草AV蜜桃| 成人资源影音先锋久久资源网| 久久亚洲精品人成综合网| 久久九九亚洲精品| 中文成人无码精品久久久不卡| 无码伊人66久久大杳蕉网站谷歌| 久久婷婷国产麻豆91天堂| 久久久久人妻一区精品果冻| 亚洲中文字幕久久精品无码APP | 亚洲国产成人久久综合碰碰动漫3d| 国产无套内射久久久国产| 精品久久久无码21p发布| 国产亚洲欧美成人久久片| 久久久国产视频| A级毛片无码久久精品免费| 久久九九精品99国产精品| 久久亚洲视频| 久久精品国产免费| 久久婷婷五月综合国产尤物app| 久久综合一区二区无码| 久久精品国产精品青草app| 人妻精品久久久久中文字幕一冢本| 久久久WWW免费人成精品| 亚洲国产精品一区二区久久| 久久婷婷五月综合色高清| 久久只这里是精品66| 久久久无码精品亚洲日韩软件| 久久亚洲国产欧洲精品一| 精品久久久久久无码专区 | 色综合合久久天天综合绕视看| 亚洲精品乱码久久久久久按摩| 久久夜色撩人精品国产| 久久精品成人免费观看97| 国产成人精品久久亚洲高清不卡 | 久久久久久久97| 999久久久免费精品国产| 国产午夜免费高清久久影院| 久久精品无码专区免费青青| 国产午夜免费高清久久影院| 色噜噜狠狠先锋影音久久|