• <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>

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

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

            常用鏈接

            留言簿(1)

            我參與的團(tuán)隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             1. 數(shù)組操作:
                在Lua中,“數(shù)組”只是table的一個別名,是指以一種特殊的方法來使用table。出于性能原因,Lua的C API為數(shù)組操作提供了專門的函數(shù),如:
                void lua_rawgeti(lua_State* L, int index, int key);
                void lua_rawseti(lua_State* L, int index, int key);
                以上兩個函數(shù)分別用于讀取和設(shè)置數(shù)組中的元素值。其中index參數(shù)表示待操作的table在棧中的位置,key表示元素在table中的索引值。由于這兩個函數(shù)均為原始操作,比涉及元表的table訪問更快。通常而言,作為數(shù)組使用的table很少會用到元表。
                見如下代碼示例和關(guān)鍵性注釋:

            復(fù)制代碼
            1 #include <stdio.h>  
            2
            #include <string.h>
            3
            #include <lua.hpp>
            4
            #include <lauxlib.h>
            5
            #include <lualib.h>
            6

            7
            extern "C" int mapFunc(lua_State* L)
            8
            {
            9
            //檢查Lua調(diào)用代碼中傳遞的第一個參數(shù)必須是table。否則將引發(fā)錯誤。
            10 luaL_checktype(L,1,LUA_TTABLE);
            11 luaL_checktype(L,2,LUA_TFUNCTION);
            12 //獲取table中的字段數(shù)量,即數(shù)組的元素數(shù)量。
            13 int n = lua_objlen(L,1);
            14 //Lua中的數(shù)組起始索引習(xí)慣為1,而不是C中的0。
            15 for (int i = 1; i <= n; ++i) {
            16 lua_pushvalue(L,2); //將Lua參數(shù)中的function(第二個參數(shù))的副本壓入棧中。
            17 lua_rawgeti(L,1,i); //壓入table[i]
            18 lua_call(L,1,1); //調(diào)用function(table[i]),并將函數(shù)結(jié)果壓入棧中。
            19 lua_rawseti(L,1,i); //table[i] = 函數(shù)返回值,同時將返回值彈出棧。
            20 }
            21
            22 //無結(jié)果返回給Lua代碼。
            23 return 0;
            24 }
            復(fù)制代碼

                2. 字符串操作:
                當(dāng)一個C函數(shù)從Lua收到一個字符串參數(shù)時,必須遵守兩條規(guī)則:不要在訪問字符串時從棧中將其彈出,不要修改字符串。在Lua的C API中主要提供了兩個操作Lua字符串的函數(shù),即:
                void  lua_pushlstring(lua_State *L, const char *s, size_t l);
                const char* lua_pushfstring(lua_State* L, const char* fmt, ...);
                第一個API用于截取指定長度的子字符串,同時將其壓入棧中。而第二個API則類似于C庫中的sprintf函數(shù),并將格式化后的字符串壓入棧中。和sprintf的格式說明符不同的是,該函數(shù)只支持%%(表示字符%)、%s(表示字符串)、%d(表示整數(shù))、%f(表示Lua中的number)及%c(表示字符)。除此之外,不支持任何例如寬度和精度的選項。

            復(fù)制代碼
            1 #include <stdio.h>  
            2
            #include <string.h>
            3
            #include <lua.hpp>
            4
            #include <lauxlib.h>
            5
            #include <lualib.h>
            6

            7
            extern "C" int splitFunc(lua_State* L)
            8
            {
            9 const char* s = luaL_checkstring(L,1);
            10 const char* sep = luaL_checkstring(L,2); //分隔符
            11 const char* e;
            12 int i = 1;
            13 lua_newtable(L); //結(jié)果table
            14 while ((e = strchr(s,*sep)) != NULL) {
            15 lua_pushlstring(L,s,e - s); //壓入子字符串。
            16 //將剛剛壓入的子字符串設(shè)置給table,同時賦值指定的索引值。
            17 lua_rawseti(L,-2,i++);
            18 s = e + 1;
            19 }
            20 //壓入最后一個子串
            21 lua_pushstring(L,s);
            22 lua_rawseti(L,-2,i);
            23 return 1; //返回table。
            24 }
            復(fù)制代碼

                Lua API中提供了lua_concat函數(shù),其功能類似于Lua中的".."操作符,用于連接(并彈出)棧頂?shù)膎個值,然后壓入連接后的結(jié)果。其原型為:
                void  lua_concat(lua_State *L, int n);
                參數(shù)n表示棧中待連接的字符串?dāng)?shù)量。該函數(shù)會調(diào)用元方法。然而需要說明的是,如果連接的字符串?dāng)?shù)量較少,該函數(shù)可以很好的工作,反之,則會帶來性能問題。為此,Lua API提供了另外一組函數(shù)專門解決由此而帶來的性能問題,見如下代碼示例:

            復(fù)制代碼
            1 #include <stdio.h>  
            2
            #include <string.h>
            3
            #include <lua.hpp>
            4
            #include <lauxlib.h>
            5
            #include <lualib.h>
            6

            7
            extern "C" int strUpperFunc(lua_State* L)
            8
            {
            9
            size_t len;
            10 luaL_Buffer b;
            11 //檢查參數(shù)第一個參數(shù)是否為字符串,同時返回字符串的指針及長度。
            12 const char* s = luaL_checklstring(L,1,&len);
            13 //初始化Lua的內(nèi)部Buffer。
            14 luaL_buffinit(L,&b);
            15 //將處理后的字符依次(luaL_addchar)追加到Lua的內(nèi)部Buffer中。
            16 for (int i = 0; i < len; ++i)
            17 luaL_addchar(&b,toupper(s[i]));
            18 //將該Buffer及其內(nèi)容壓入棧中。
            19 luaL_pushresult(&b);
            20 return 1;
            21 }
            復(fù)制代碼

                使用緩沖機(jī)制的第一步是聲明一個luaL_Buffer變量,并用luaL_buffinit來初始化它。初始化后,就可通過luaL_addchar將一個字符放入緩沖。除該函數(shù)之外,Lua的輔助庫還提供了直接添加字符串的函數(shù),如:
                void luaL_addlstring(luaL_Buffer* b, const char* s, size_t len);
                void luaL_addstring(luaL_Buffer* b, const char* s);
                最后luaL_pushresult會更新緩沖,并將最終的字符串留在棧頂。通過這些函數(shù),就無須再關(guān)心緩沖的分配了。但是在追加的過程中,緩沖會將一些中間結(jié)果放到棧中。因此,在使用時要留意此細(xì)節(jié),只要保證壓入和彈出的次數(shù)相等既可。Lua API還提供一個比較常用的函數(shù),用于將棧頂?shù)淖址驍?shù)字也追加到緩沖區(qū)中,函數(shù)原型為:
                void luaL_addvalue(luaL_Buffer* b);
                
                3. 在C函數(shù)中保存狀態(tài):
                Lua API提供了三種方式來保存非局部變量,即注冊表、環(huán)境和upvalue。
                1). 注冊表:
                注冊表是一個全局的table,只能被C代碼訪問。通常用于保存多個模塊間的共享數(shù)據(jù)。我們可以通過LUA_REGISTRYINDEX索引值來訪問注冊表。

            復(fù)制代碼
            1 #include <stdio.h>  
            2
            #include <string.h>
            3
            #include <lua.hpp>
            4
            #include <lauxlib.h>
            5
            #include <lualib.h>
            6

            7
            void registryTestFunc(lua_State* L)
            8
            {
            9
            lua_pushstring(L,"Hello");
            10 lua_setfield(L,LUA_REGISTRYINDEX,"key1");
            11 lua_getfield(L,LUA_REGISTRYINDEX,"key1");
            12 printf("%s\n",lua_tostring(L,-1));
            13 }
            14
            15 int main()
            16 {
            17 lua_State* L = luaL_newstate();
            18 registryTestFunc(L);
            19 lua_close(L);
            20 return 0;
            21 }
            復(fù)制代碼

                2). 環(huán)境:
                如果需要保存一個模塊的私有數(shù)據(jù),即模塊內(nèi)各函數(shù)需要共享的數(shù)據(jù),應(yīng)該使用環(huán)境。我們可以通過LUA_ENVIRONINDEX索引值來訪問環(huán)境。

            復(fù)制代碼
            1 #include <lua.hpp>  
            2
            #include <lauxlib.h>
            3
            #include <lualib.h>
            4

            5
            //模塊內(nèi)設(shè)置環(huán)境數(shù)據(jù)的函數(shù)
            6
            extern "C" int setValue(lua_State* L)
            7
            {
            8
            lua_pushstring(L,"Hello");
            9
            lua_setfield(L,LUA_ENVIRONINDEX,"key1");
            10 return 0;
            11 }
            12
            13 //模塊內(nèi)獲取環(huán)境數(shù)據(jù)的函數(shù)
            14 extern "C" int getValue(lua_State* L)
            15 {
            16 lua_getfield(L,LUA_ENVIRONINDEX,"key1");
            17 printf("%s\n",lua_tostring(L,-1));
            18 return 0;
            19 }
            20
            21 static luaL_Reg myfuncs[] = {
            22 {"setValue", setValue},
            23 {"getValue", getValue},
            24 {NULL, NULL}
            25 };
            26
            27
            28 extern "C" __declspec(dllexport)
            29 int luaopen_testenv(lua_State* L)
            30 {
            31 lua_newtable(L); //創(chuàng)建一個新的表用于環(huán)境
            32 lua_replace(L,LUA_ENVIRONINDEX); //將剛剛創(chuàng)建并壓入棧的新表替換為當(dāng)前模塊的環(huán)境表。
            33 luaL_register(L,"testenv",myfuncs);
            34 return 1;
            35 }
            復(fù)制代碼

                Lua測試代碼如下。

            1 require "testenv" 
            2
            3 print(testenv.setValue())
            4 print(testenv.getValue())
            5 --輸出為:Hello

                3). upvalue:
                upvalue是和特定函數(shù)關(guān)聯(lián)的,我們可以將其簡單的理解為函數(shù)內(nèi)的靜態(tài)變量。 

            復(fù)制代碼
            1 #include <lua.hpp>  
            2
            #include <lauxlib.h>
            3
            #include <lualib.h>
            4

            5
            extern "C" int counter(lua_State* L)
            6
            {
            7
            //獲取第一個upvalue的值。
            8
            int val = lua_tointeger(L,lua_upvalueindex(1));
            9
            //將得到的結(jié)果壓入棧中。
            10 lua_pushinteger(L,++val);
            11 //賦值一份棧頂?shù)臄?shù)據(jù),以便于后面的替換操作。
            12 lua_pushvalue(L,-1);
            13 //該函數(shù)將棧頂?shù)臄?shù)據(jù)替換到upvalue(1)中的值。同時將棧頂數(shù)據(jù)彈出。
            14 lua_replace(L,lua_upvalueindex(1));
            15 //lua_pushinteger(L,++value)中壓入的數(shù)據(jù)仍然保留在棧中并返回給Lua。
            16 return 1;
            17 }
            18
            19 extern "C" int newCounter(lua_State* L)
            20 {
            21 //壓入一個upvalue的初始值0,該函數(shù)必須先于lua_pushcclosure之前調(diào)用。
            22 lua_pushinteger(L,0);
            23 //壓入閉包函數(shù),參數(shù)1表示該閉包函數(shù)的upvalue數(shù)量。該函數(shù)返回值,閉包函數(shù)始終位于棧頂。
            24 lua_pushcclosure(L,counter,1);
            25 return 1;
            26 }
            27
            28 static luaL_Reg myfuncs[] = {
            29 {"counter", counter},
            30 {"newCounter", newCounter},
            31 {NULL, NULL}
            32 };
            33
            34
            35 extern "C" __declspec(dllexport)
            36 int luaopen_testupvalue(lua_State* L)
            37 {
            38 luaL_register(L,"testupvalue",myfuncs);
            39 return 1;
            40 }
            復(fù)制代碼

                Lua測試代碼如下。

            復(fù)制代碼
            1 require "testupvalue"  
            2

            3
            func = testupvalue.newCounter();
            4
            print(func());
            5
            print(func());
            6
            print(func());
            7

            8
            func = testupvalue.newCounter();
            9
            print(func());
            10 print(func());
            11 print(func());
            12
            13 --[[ 輸出結(jié)果為: 14 1 15 2 16 3 17 1 18 2 19 3 20 --]] 
            復(fù)制代碼
            posted on 2014-02-17 17:45 沛沛 閱讀(267) 評論(0)  編輯 收藏 引用 所屬分類: Script
            久久丝袜精品中文字幕| 国产伊人久久| 丁香五月综合久久激情| 思思久久精品在热线热| 日本三级久久网| 色婷婷综合久久久久中文 | 精品久久久久久中文字幕| 久久AV高潮AV无码AV| 欧美激情精品久久久久久久九九九| 国产99久久久国产精品小说| 国产精品岛国久久久久| 99久久99久久| 欧美精品丝袜久久久中文字幕 | 精品久久久久久无码中文字幕一区| 思思久久精品在热线热| 久久精品人人做人人爽电影| 一本一本久久a久久综合精品蜜桃| 一级女性全黄久久生活片免费 | 亚洲AV日韩精品久久久久 | 国产成人久久精品激情| 中文精品久久久久人妻| 国内精品免费久久影院| 国产精品岛国久久久久| 久久久久久久人妻无码中文字幕爆| 一本一本久久A久久综合精品| 精品国产青草久久久久福利| www性久久久com| 国产亚洲美女精品久久久2020| 久久精品国产一区二区| 国产成人无码精品久久久性色| 久久激情亚洲精品无码?V| 色综合久久中文色婷婷| 久久电影网2021| 2022年国产精品久久久久| 久久99久久99精品免视看动漫| 伊人久久久AV老熟妇色| 亚洲人成网亚洲欧洲无码久久| 亚洲欧美一级久久精品| 国产精品99久久久精品无码 | 久久精品国产亚洲一区二区| 久久99精品国产99久久|