Lua使用心得

2021-08-02 10:11:29 字數 3368 閱讀 9745

這幾天研究了一下lua,主要關注的是lua和vc之間的整合,把**都寫好放在vc宿主程式裡,然後在lua裡呼叫宿主程式的這些**(或者叫介面、元件,隨便你怎麼叫),希望能用指令碼來控制主程式的行為。這實際上也是一種把業務分離,用指令碼控制的架構,可能有些人把這種指令碼叫做業務引擎,工作流等。

為什麼選擇lua?

因為它是乙個能和c/c++結合得很緊的指令碼語言,而我們的程式是用vc++ 寫的;另外一點是因為它的名氣,連wow都用lua來提供api讓玩家修改其遊戲行為,那我是找不到什麼理由拒絕它了。

lua是什麼?在**獲取lua?

lua和vc mfc的整合?

extern "c"

lua_state *lua;

在某個適當的地方(我是在oninitdialog裡)呼叫下面一段**,這段**的作用是開啟一些必要的庫:

lua = lua_open (); 

if(lua)

用完lua的時候,呼叫下面一句來關閉lua庫:

lua_close (lua);

好了,到現在為止,lua已經完全變成我們程式的一部分了,試著編譯一下,看看能不能順利通過。。。

lua和mfc的互動?

lua變成我們程式的一部分之後,我們還要使用它,要記住我們的目標是用指令碼程式控制我們宿主程式的執行流程,那我們就要完成兩步,一是用mfc程式呼叫lua的函式,二是用lua呼叫mfc的函式,下面的內容對於初學者可能會開始有點難理解了,請打醒十二分精神,我會盡量簡單的說。。。

1、 mfc呼叫lua的函式,這裡用到乙個stackdump的函式,是關於主程式和lua的互動棧的問題,下面會對互動棧的問題專門說明。

首先我們用記事本建立乙個test.lua,內容是乙個相加函式:

function add ( x, y )

return x + y;

end

然後再vc裡呼叫它,如下的一段**,看這段**的時候,先把stackdump函式忽略,只需要知道它是乙個輸出lua和vc互動棧內容的函式,對了,你可以新建乙個button的click函式,然後把這段**放進去:

stackdump(lua);   

lual_dofile(lua, "test.lua");     // 解釋分析lua檔案

stackdump(lua);

lua_getglobal(lua, "add");       // 取到乙個全域性標號add,取的同時會把add函式壓棧

stackdump(lua);   

lua_pushnumber(lua, 1);        // 把第乙個引數壓入棧裡

stackdump(lua);

lua_pushnumber(lua, 2);        // 第二個引數壓棧

stackdump(lua);

//lua_call(lua, 2, 1);

if(lua_pcall(lua, 2, 1, 0) != 0)        // 執行add函式

stackdump(lua);

int d = (int)lua_tonumber(lua, -1);        // 函式執行完了,執行結果被壓棧,所以取得最頂端的乙個數就是結果值,-1就是指取棧頂的值

cstring str;

str.format("%d", d);

afxmessagebox(str);

stackdump(lua);

lua_pop(lua, 1);      // 把值從棧裡清除,pop(彈出)乙個值

stackdump(lua);

好好分析一下這段**,我們大概知道呼叫lua函式的乙個過程是:dofile--〉函式名壓棧--〉引數依序壓棧--〉lua_pcall執行(執行結果壓棧)--〉取出執行結果(如果有多個,就從棧裡取出多個。。。),這樣我們就能很輕鬆的呼叫到lua裡的函式,其實就是要知道棧裡發生了什麼。。。

2、 lua呼叫mfc函式,比如我們想在lua裡呼叫乙個msg函式,能彈出乙個視窗來顯示我們想顯示的字串,然後返回值是1個"msgok!"字串。

lua檔案是這樣的,第一句是呼叫msg函式,第二句是測試返回的字串是不是"msgok!":

c = msg ("123");

msg(c);

mfc程式裡是這樣的:

static int msg(lua_state* l)

然後就匯出這個函式,如下:

lua_pushcfunction(lua, msg);

lua_setglobal(lua, "msg");

接著就執行剛才的lua檔案就行了,記得執行之前要先lua_open () 哦:

lual_dofile(lua, "test.lua");

執行的結果就是連續跳出兩個messagebox,第乙個是123,第二個是"msgok!",說明我們返回的字串被lua接收到了,lua的第二行我們沒有接收它的返回值,則這個返回值會自動被拋棄了。

如果需要多返回值,則我們要把下面一句:

lua_pushlstring(l, "msgok!", 6);  // 把返回值壓進棧裡

// 這個返回是指返回值的個數

return 1;

改為:lua_pushlstring(l, "msgok!", 6);  // 把返回值壓進棧裡

lua_pushlstring(l, "haha!", 5);      // 把返回值壓進棧裡

// 這個返回是指返回值的個數

return 2;

這樣我們在lua檔案裡就可以像下面一樣取得兩個返回值了:

c,d = msg("123");

那c和d就分別是"msgok!"和"haha!"兩個字串了。 這種自動機制用起來還是比較方便的。

3、互動棧

上面兩個呼叫其實都是對lua棧的實用,那我們就要好好理解乙個概念,lua和vc的互動棧(棧是什麼?請參考資料結構的書哈。。。)lua和vc就是通過這個棧來實現互動的,這個棧的訪問函式有lua_gettop,lua_settop,lua_tostring,lua_to***等等的函式,我們要清楚當乙個函式呼叫發生的時候,棧裡是發生了什麼。上面我用了乙個stackdump函式,當我們呼叫的時候,能很清楚的看到棧裡發生了什麼。

首先我們要知道從棧頂往下數就是-1、-2,從棧底往上數就是1、2。

如果使用lua_gettop(l, 1),就是取得棧底第乙個元素。lua_gettop(l, -1)就是取得棧頂的第乙個元素。lua_pop() (l, 1)就是把棧頂的乙個元素彈出來,lua_pop()(l, 2)就是把棧頂的兩個元素彈出。

好了,寫了一通,最後是這個stackdump函式的實現:

int stackdump(lua_state* l)

outputdebugstring("/n"); }

return 0; }

Lua使用心得 2

在lua指令碼呼叫中,如果我們碰到一種不好的指令碼,例如 while 1 do doend 那我們的程式主線程也會被阻塞住。那我們如何防止這種問題呢?下面就給出乙個解決的辦法。首先為了不阻塞主線程,那我們就要開乙個執行緒,把處理指令碼的操作都放在這個新開的工作執行緒裡。要詳細了解工作執行緒和介面執行...

frameset 使用心得

欲明白本篇 html徹底剖析 之標記分類,請看 標記一覽 也請先明白圍堵標記與空標記的分別,請看 html概念 框架概念 謂框架便是網頁畫面分成幾個框窗,同時取得多個 url。只需要 即可,面所有框架標記需要放在乙個總起的 html 檔,這個檔案只記錄了該框架如何分割 不會顯示任何資料,所以不必放入...

Access使用心得

今天臨時用access做資料庫,長期用sql server開發習慣了,總結一下現在為止用到的比較大的差異,以後有新的再補了 1 返回字串長度 len s lenb s 前者返回字元數,後者返回位元組數,並且access中text型別字元統一為2位元組,與sql2000不同。2 join的使用 acc...