青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

每天早晨叫醒你的不是鬧鐘,而是夢想

  C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
  62 Posts :: 0 Stories :: 5 Comments :: 0 Trackbacks

常用鏈接

留言簿(1)

我參與的團隊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

   Lua是一種嵌入式腳本語言,即Lua不是可以單獨運行的程序,在實際應(yīng)用中,主要存在兩種應(yīng)用形式。第一種形式是,C/C++作為主程序,調(diào)用Lua代碼,此時可以將Lua看做“可擴展的語言”,我們將這種應(yīng)用稱為“應(yīng)用程序代碼”。第二種形式是Lua具有控制權(quán),而C/C++代碼則作為Lua的“庫代碼”。在這兩種形式中,都是通過Lua提供的C API完成兩種語言之間的通信的。

    1. 基礎(chǔ)知識:
    C API是一組能使C/C++代碼與Lua交互的函數(shù)。其中包括讀寫Lua全局變量、調(diào)用Lua函數(shù)、運行一段Lua代碼,以及注冊C函數(shù)以供Lua代碼調(diào)用等。這里先給出一個簡單的示例代碼:

復制代碼
 1 #include <stdio.h>
2 #include <string.h>
3 #include <lua.hpp>
4 #include <lauxlib.h>
5 #include <lualib.h>
6
7 int main(void)
8 {
9 const char* buff = "print(\"hello\")";
10 int error;
11 lua_State* L = luaL_newstate();
12 luaL_openlibs(L);
13
14 error = luaL_loadbuffer(L,buff,strlen(buff),"line") || lua_pcall(L,0,0,0);
15 int s = lua_gettop(L);
16 if (error) {
17 fprintf(stderr,"%s",lua_tostring(L,-1));
18 lua_pop(L,1);
19 }
20 lua_close(L);
21 return 0;
22 }
復制代碼

    下面是針對以上代碼給出的具體解釋:
    1). 上面的代碼是基于我的C++工程,而非C工程,因此包含的頭文件是lua.hpp,如果是C工程,可以直接包含lua.h。
    2). Lua庫中沒有定義任何全局變量,而是將所有的狀態(tài)都保存在動態(tài)結(jié)構(gòu)lua_State中,后面所有的C API都需要該指針作為第一個參數(shù)。
    3). luaL_openlibs函數(shù)是用于打開Lua中的所有標準庫,如io庫、string庫等。
    4). luaL_loadbuffer編譯了buff中的Lua代碼,如果沒有錯誤,則返回0,同時將編譯后的程序塊壓入虛擬棧中。
    5). lua_pcall函數(shù)會將程序塊從棧中彈出,并在保護模式下運行該程序塊。執(zhí)行成功返回0,否則將錯誤信息壓入棧中。
    6). lua_tostring函數(shù)中的-1,表示棧頂?shù)乃饕担瑮5椎乃饕禐?,以此類推。該函數(shù)將返回棧頂?shù)腻e誤信息,但是不會將其從棧中彈出。
    7). lua_pop是一個宏,用于從虛擬棧中彈出指定數(shù)量的元素,這里的1表示僅彈出棧頂?shù)脑亍?br />    8). lua_close用于釋放狀態(tài)指針所引用的資源。

    2. 棧:
    在Lua和C語言之間進行數(shù)據(jù)交換時,由于兩種語言之間有著較大的差異,比如Lua是動態(tài)類型,C語言是靜態(tài)類型,Lua是自動內(nèi)存管理,而C語言則是手動內(nèi)存管理。為了解決這些問題,Lua的設(shè)計者使用了虛擬棧作為二者之間數(shù)據(jù)交互的介質(zhì)。在C/C++程序中,如果要獲取Lua的值,只需調(diào)用Lua的C API函數(shù),Lua就會將指定的值壓入棧中。要將一個值傳給Lua時,需要先將該值壓入棧,然后調(diào)用Lua的C API,Lua就會獲取該值并將其從棧中彈出。為了可以將不同類型的值壓入棧,以及從棧中取出不同類型的值,Lua為每種類型均設(shè)定了一個特定函數(shù)。
    1). 壓入元素:
    Lua針對每種C類型,都有一個C API函數(shù)與之對應(yīng),如:
    void lua_pushnil(lua_State* L);  --nil值
    void lua_pushboolean(lua_State* L, int b); --布爾值
    void lua_pushnumber(lua_State* L, lua_Number n); --浮點數(shù)
    void lua_pushinteger(lua_State* L, lua_Integer n);  --整型
    void lua_pushlstring(lua_State* L, const char* s, size_t len); --指定長度的內(nèi)存數(shù)據(jù)
    void lua_pushstring(lua_State* L, const char* s);  --以零結(jié)尾的字符串,其長度可由strlen得出。
    對于字符串數(shù)據(jù),Lua不會持有他們的指針,而是調(diào)用在API時生成一個內(nèi)部副本,因此,即使在這些函數(shù)返回后立刻釋放或修改這些字符串指針,也不會有任何問題。
    在向棧中壓入數(shù)據(jù)時,可以通過調(diào)用下面的函數(shù)判斷是否有足夠的棧空間可用,一般而言,Lua會預(yù)留20個槽位,對于普通應(yīng)用來說已經(jīng)足夠了,除非是遇到有很多參數(shù)的函數(shù)。
    int lua_checkstack(lua_State* L, int extra) --期望得到extra數(shù)量的空閑槽位,如果不能擴展并獲得,返回false。 
    
    2). 查詢元素:
    API使用“索引”來引用棧中的元素,第一個壓入棧的為1,第二個為2,依此類推。我們也可以使用負數(shù)作為索引值,其中-1表示為棧頂元素,-2為棧頂下面的元素,同樣依此類推。
    Lua提供了一組特定的函數(shù)用于檢查返回元素的類型,如:
    int lua_isboolean (lua_State *L, int index);
    int lua_iscfunction (lua_State *L, int index);
    int lua_isfunction (lua_State *L, int index);
    int lua_isnil (lua_State *L, int index);
    int lua_islightuserdata (lua_State *L, int index);
    int lua_isnumber (lua_State *L, int index);
    int lua_isstring (lua_State *L, int index);
    int lua_istable (lua_State *L, int index);
    int lua_isuserdata (lua_State *L, int index);
    以上函數(shù),成功返回1,否則返回0。需要特別指出的是,對于lua_isnumber而言,不會檢查值是否為數(shù)字類型,而是檢查值是否能轉(zhuǎn)換為數(shù)字類型。
    Lua還提供了一個函數(shù)lua_type,用于獲取元素的類型,函數(shù)原型如下:
    int lua_type (lua_State *L, int index);
    該函數(shù)的返回值為一組常量值,分別是:LUA_TNIL、LUA_TNUMBER、LUA_TBOOLEAN、LUA_TSTRING、LUA_TTABLE、LUA_TFUNCTION、LUA_TUSERDATA、LUA_TTHREAD和LUA_TLIGHTUSERDATA。這些常量通常用于switch語句中。
    除了上述函數(shù)之外,Lua還提供了一組轉(zhuǎn)換函數(shù),如:
    int lua_toboolean (lua_State *L, int index);
    lua_CFunction lua_tocfunction (lua_State *L, int index);
    lua_Integer lua_tointeger (lua_State *L, int index);    
    const char *lua_tolstring (lua_State *L, int index, size_t *len);
    lua_Number lua_tonumber (lua_State *L, int index);
    const void *lua_topointer (lua_State *L, int index);
    const char *lua_tostring (lua_State *L, int index);
    void *lua_touserdata (lua_State *L, int index);
    --string類型返回字符串長度,table類型返回操作符'#'等同的結(jié)果,userdata類型返回分配的內(nèi)存塊長度。
    size_t lua_objlen (lua_State *L, int index); 
    對于上述函數(shù),如果調(diào)用失敗,lua_toboolean、lua_tonumber、lua_tointeger和lua_objlen均返回0,而其他函數(shù)則返回NULL。在很多時候0不是一個很有效的用于判斷錯誤的值,但是ANSI C沒有提供其他可以表示錯誤的值。因此對于這些函數(shù),在有些情況下需要先使用lua_is*系列函數(shù)判斷是否類型正確,而對于剩下的函數(shù),則可以直接通過判斷返回值是否為NULL即可。
    對于lua_tolstring函數(shù)返回的指向內(nèi)部字符串的指針,在該索引指向的元素被彈出之后,將無法保證仍然有效。該函數(shù)返回的字符串末尾均會有一個尾部0。
    下面將給出一個工具函數(shù),可用于演示上面提到的部分函數(shù),如:

復制代碼
 1 static void stackDump(lua_State* L) 
2 {
3 int top = lua_gettop(L);
4 for (int i = 1; i <= top; ++i) {
5 int t = lua_type(L,i);
6 switch(t) {
7 case LUA_TSTRING:
8 printf("'%s'",lua_tostring(L,i));
9 break;
10 case LUA_TBOOLEAN:
11 printf(lua_toboolean(L,i) ? "true" : "false");
12 break;
13 case LUA_TNUMBER:
14 printf("%g",lua_tonumber(L,i));
15 break;
16 default:
17 printf("%s",lua_typename(L,t));
18 break;
19 }
20 printf("");
21 }
22 printf("\n");
23 }
復制代碼

    3). 其它棧操作函數(shù):
    除了上面給出的數(shù)據(jù)交換函數(shù)之外,Lua的C API還提供了一組用于操作虛擬棧的普通函數(shù),如:
    int lua_gettop(lua_State* L); --返回棧中元素的個數(shù)。
    void lua_settop(lua_State* L, int index); --將棧頂設(shè)置為指定的索引值。
    void lua_pushvalue(lua_State* L, int index); --將指定索引的元素副本壓入棧。
    void lua_remove(lua_State* L, int index); --刪除指定索引上的元素,其上面的元素自動下移。
    void lua_insert(lua_State* L, int index); --將棧頂元素插入到該索引值指向的位置。
    void lua_replace(lua_State* L, int index); --彈出棧頂元素,并將該值設(shè)置到指定索引上。
    Lua還提供了一個宏用于彈出指定數(shù)量的元素:#define lua_pop(L,n)  lua_settop(L, -(n) - 1)    
    見如下示例代碼:

復制代碼
 1 int main()
2 {
3 lua_State* L = luaL_newstate();
4 lua_pushboolean(L,1);
5 lua_pushnumber(L,10);
6 lua_pushnil(L);
7 lua_pushstring(L,"hello");
8 stackDump(L); //true 10 nil 'hello'
9
10 lua_pushvalue(L,-4);
11 stackDump(L); //true 10 nil 'hello' true
12
13 lua_replace(L,3);
14 stackDump(L); //true 10 true 'hello'
15
16 lua_settop(L,6);
17 stackDump(L); //true 10 true 'hello' nil nil
18
19 lua_remove(L,-3);
20 stackDump(L); //true 10 true nil nil
21
22 lua_settop(L,-5);
23 stackDump(L); //true
24
25 lua_close(L);
26 return 0;
27 }
復制代碼


    3. C API中的錯誤處理:
    1). C程序調(diào)用Lua代碼的錯誤處理:
    通常情況下,應(yīng)用程序代碼是以“無保護”模式運行的。因此,當Lua發(fā)現(xiàn)“內(nèi)存不足”這類錯誤時,只能通過調(diào)用“緊急”函數(shù)來通知C語言程序,之后在結(jié)束應(yīng)用程序。用戶可通過lua_atpanic來設(shè)置自己的“緊急”函數(shù)。如果希望應(yīng)用程序代碼在發(fā)生Lua錯誤時不會退出,可通過調(diào)用lua_pcall函數(shù)以保護模式運行Lua代碼。這樣再發(fā)生內(nèi)存錯誤時,lua_pcall會返回一個錯誤代碼,并將解釋器重置為一致的狀態(tài)。如果要保護與Lua的C代碼,可以使用lua_cpall函數(shù),它將接受一個C函數(shù)作為參數(shù),然后調(diào)用這個C函數(shù)。
    
    2). Lua調(diào)用C程序:
    通常而言,當一個被Lua調(diào)用的C函數(shù)檢測到錯誤時,它就應(yīng)該調(diào)用lua_error,該函數(shù)會清理Lua中所有需要清理的資源,然后跳轉(zhuǎn)回發(fā)起執(zhí)行的那個lua_pcall,并附上一條錯誤信息。

posted on 2014-02-17 17:44 沛沛 閱讀(337) 評論(0)  編輯 收藏 引用 所屬分類: Script
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品第十页| 亚洲激情视频网站| 国内外成人免费激情在线视频网站| 欧美日精品一区视频| 欧美精品久久99| 欧美日韩不卡一区| 欧美午夜性色大片在线观看| 国产精品日韩专区| 国产午夜一区二区三区| 国产深夜精品| 有坂深雪在线一区| 日韩午夜在线电影| 亚洲欧美精品在线| 久久精品中文| 亚洲高清在线视频| 亚洲图片在线| 久久露脸国产精品| 欧美日韩亚洲另类| 国内外成人在线视频| 亚洲人成网站影音先锋播放| 亚洲一区欧美二区| 美女视频一区免费观看| 亚洲片区在线| 久久精品人人做人人爽电影蜜月| 你懂的国产精品| 美女露胸一区二区三区| 欧美日韩一视频区二区| 国产视频自拍一区| 亚洲激情视频网站| 午夜精品影院| 亚洲第一页在线| 亚洲欧美日韩一区二区在线 | 久久理论片午夜琪琪电影网| 欧美激情一区在线观看| 国产亚洲欧洲一区高清在线观看| 亚洲精品日韩一| 欧美自拍偷拍| 9久re热视频在线精品| 久久久久在线| 国产日韩一区二区三区| 亚洲午夜视频在线| 男人插女人欧美| 亚洲男人第一av网站| 欧美成人精品三级在线观看| 国产一区二区三区久久精品| 亚洲欧洲av一区二区| 日韩一级不卡| 免费日韩成人| 激情视频亚洲| 久久这里只有| 欧美一区二区三区四区夜夜大片| 国产精品草莓在线免费观看| 亚洲精品人人| 欧美电影免费观看高清完整版| 欧美一级电影久久| 国产精品久久夜| 亚洲色图制服丝袜| 亚洲人成网站精品片在线观看| 久久精彩免费视频| 韩国成人精品a∨在线观看| 亚洲午夜精品福利| 亚洲美女免费精品视频在线观看| 欧美激情亚洲国产| 亚洲伦理在线免费看| 亚洲第一天堂av| 欧美国产日韩在线观看| 亚洲日本免费| 亚洲精华国产欧美| 欧美精品亚洲一区二区在线播放| 亚洲人体一区| 亚洲精选久久| 欧美天堂亚洲电影院在线观看| 一区二区日韩伦理片| 日韩亚洲欧美在线观看| 国产精品久久久久91| 午夜一区二区三区在线观看| 亚洲综合好骚| 一区二区三区在线不卡| 欧美freesex8一10精品| 嫩草伊人久久精品少妇av杨幂| 亚洲欧洲一区二区三区久久| 亚洲国产精品一区二区第一页 | 久久久久国内| 欧美88av| 日韩视频永久免费| 亚洲国产日韩欧美在线图片| 欧美精品18videos性欧美| 一二三区精品| 亚洲免费视频在线观看| 黄页网站一区| 亚洲精品乱码久久久久久蜜桃91| 欧美日韩性生活视频| 久久精品视频一| 欧美成人激情视频| 亚洲欧美国产视频| 久久久久久亚洲精品中文字幕| 亚洲欧洲精品成人久久奇米网| 亚洲区一区二区三区| 国产日韩欧美在线看| 能在线观看的日韩av| 欧美视频一区二区三区四区| 久久精品国产亚洲高清剧情介绍| 蜜臀久久99精品久久久久久9| 亚洲一区在线观看视频 | 亚洲最新视频在线播放| 亚洲一区二区av电影| 亚洲精华国产欧美| 亚洲制服丝袜在线| 亚洲精品在线观| 欧美一区二区三区日韩| 亚洲午夜精品久久久久久app| 久久久人人人| 久久成人精品无人区| 欧美日韩精品一区二区天天拍小说| 久久久久久久尹人综合网亚洲| 欧美视频久久| 亚洲黄色在线视频| 伊人久久噜噜噜躁狠狠躁| 亚洲字幕一区二区| 亚洲在线成人| 欧美久久久久久蜜桃| 欧美成人黄色小视频| 精品白丝av| 久久国产精品久久久| 欧美在线亚洲综合一区| 国产精品国产三级国产普通话三级 | 欧美有码在线观看视频| 欧美深夜福利| 亚洲裸体视频| av不卡免费看| 欧美日韩小视频| 99在线视频精品| 亚洲一区二三| 国产精品久久久爽爽爽麻豆色哟哟| 亚洲欧洲日韩在线| 亚洲靠逼com| 欧美区二区三区| 亚洲高清二区| 亚洲免费观看| 亚洲欧洲另类国产综合| 久久免费高清| 欧美成人免费在线观看| 在线精品国产欧美| 久色成人在线| 亚洲国产精品一区二区第一页 | 蜜桃av一区| 欧美国产一区在线| 亚洲精品视频免费在线观看| 欧美大学生性色视频| 亚洲精品免费一二三区| 一区二区三区不卡视频在线观看| 欧美日韩三级一区二区| 亚洲一级免费视频| 久久精品国产v日韩v亚洲| 黄色一区二区三区四区| 女主播福利一区| 99综合在线| 久久亚洲精品网站| 99视频超级精品| 国产免费亚洲高清| 久久夜色精品国产欧美乱极品| 欧美激情乱人伦| 亚洲影院在线| 国产一区白浆| 欧美日韩国产免费| 午夜天堂精品久久久久| 久久国产免费| 亚洲人成高清| 国产精品性做久久久久久| 久久99伊人| 亚洲国产精品嫩草影院| 性欧美xxxx视频在线观看| 黄色av成人| 欧美日韩专区在线| 久久久久久成人| 中文在线资源观看网站视频免费不卡 | 99国产精品99久久久久久粉嫩| 国产精品v片在线观看不卡| 欧美一区2区三区4区公司二百| 欧美激情久久久久| 久久久av毛片精品| 亚洲午夜精品福利| 亚洲激情在线视频| 国产一区二区三区精品欧美日韩一区二区三区 | 亚洲全部视频| 国内精品久久久久久 | 亚洲精品在线一区二区| 国产女主播一区二区| 欧美成人伊人久久综合网| 亚洲欧美在线一区二区| 亚洲精品一区二区在线观看| 老牛嫩草一区二区三区日本| 午夜伦理片一区| 一区二区三区蜜桃网| 亚洲国产精品ⅴa在线观看| 国产日韩欧美在线播放不卡| 在线观看日韩av| 在线观看日产精品| 国产日韩三区| 国产精品久久综合|