国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院

首頁(yè) > 開(kāi)發(fā) > 綜合 > 正文

Lua教程(十七):C API簡(jiǎn)介

2024-07-21 23:04:46
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

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

1. 基礎(chǔ)知識(shí):

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

復(fù)制代碼 代碼如下:

#include <stdio.h>
#include <string.h>
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>

 

int main(void)
{
    const char* buff = "print(/"hello/")";
    int error;
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);

    error = luaL_loadbuffer(L,buff,strlen(buff),"line") || lua_pcall(L,0,0,0);
    int s = lua_gettop(L);
    if (error) {
        fprintf(stderr,"%s",lua_tostring(L,-1));
        lua_pop(L,1);
    }
    lua_close(L);
    return 0;
}

 


下面是針對(duì)以上代碼給出的具體解釋:

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

    2. 棧:

    在Lua和C語(yǔ)言之間進(jìn)行數(shù)據(jù)交換時(shí),由于兩種語(yǔ)言之間有著較大的差異,比如Lua是動(dòng)態(tài)類型,C語(yǔ)言是靜態(tài)類型,Lua是自動(dòng)內(nèi)存管理,而C語(yǔ)言則是手動(dòng)內(nèi)存管理。為了解決這些問(wèn)題,Lua的設(shè)計(jì)者使用了虛擬棧作為二者之間數(shù)據(jù)交互的介質(zhì)。在C/C++程序中,如果要獲取Lua的值,只需調(diào)用Lua的C API函數(shù),Lua就會(huì)將指定的值壓入棧中。要將一個(gè)值傳給Lua時(shí),需要先將該值壓入棧,然后調(diào)用Lua的C API,Lua就會(huì)獲取該值并將其從棧中彈出。為了可以將不同類型的值壓入棧,以及從棧中取出不同類型的值,Lua為每種類型均設(shè)定了一個(gè)特定函數(shù)。

    1). 壓入元素:

    Lua針對(duì)每種C類型,都有一個(gè)C API函數(shù)與之對(duì)應(yīng),如:
 

復(fù)制代碼 代碼如下:

    void lua_pushnil(lua_State* L);  --nil值
    void lua_pushboolean(lua_State* L, int b); --布爾值
    void lua_pushnumber(lua_State* L, lua_Number n); --浮點(diǎn)數(shù)
    void lua_pushinteger(lua_State* L, lua_Integer n);  --整型
    void lua_pushlstring(lua_State* L, const char* s, size_t len); --指定長(zhǎng)度的內(nèi)存數(shù)據(jù)
    void lua_pushstring(lua_State* L, const char* s);  --以零結(jié)尾的字符串,其長(zhǎng)度可由strlen得出。
 

    對(duì)于字符串?dāng)?shù)據(jù),Lua不會(huì)持有他們的指針,而是調(diào)用在API時(shí)生成一個(gè)內(nèi)部副本,因此,即使在這些函數(shù)返回后立刻釋放或修改這些字符串指針,也不會(huì)有任何問(wèn)題。
    在向棧中壓入數(shù)據(jù)時(shí),可以通過(guò)調(diào)用下面的函數(shù)判斷是否有足夠的棧空間可用,一般而言,Lua會(huì)預(yù)留20個(gè)槽位,對(duì)于普通應(yīng)用來(lái)說(shuō)已經(jīng)足夠了,除非是遇到有很多參數(shù)的函數(shù)。
    int lua_checkstack(lua_State* L, int extra) --期望得到extra數(shù)量的空閑槽位,如果不能擴(kuò)展并獲得,返回false。 
    
    2). 查詢?cè)兀?/strong>

 

    API使用“索引”來(lái)引用棧中的元素,第一個(gè)壓入棧的為1,第二個(gè)為2,依此類推。我們也可以使用負(fù)數(shù)作為索引值,其中-1表示為棧頂元素,-2為棧頂下面的元素,同樣依此類推。

    Lua提供了一組特定的函數(shù)用于檢查返回元素的類型,如:
 

復(fù)制代碼 代碼如下:

    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。需要特別指出的是,對(duì)于lua_isnumber而言,不會(huì)檢查值是否為數(shù)字類型,而是檢查值是否能轉(zhuǎn)換為數(shù)字類型。
    Lua還提供了一個(gè)函數(shù)lua_type,用于獲取元素的類型,函數(shù)原型如下:
 
復(fù)制代碼 代碼如下:

    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語(yǔ)句中。
    除了上述函數(shù)之外,Lua還提供了一組轉(zhuǎn)換函數(shù),如:
 
復(fù)制代碼 代碼如下:

    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類型返回字符串長(zhǎng)度,table類型返回操作符'#'等同的結(jié)果,userdata類型返回分配的內(nèi)存塊長(zhǎng)度。
    size_t lua_objlen (lua_State *L, int index); 
 

    對(duì)于上述函數(shù),如果調(diào)用失敗,lua_toboolean、lua_tonumber、lua_tointeger和lua_objlen均返回0,而其他函數(shù)則返回NULL。在很多時(shí)候0不是一個(gè)很有效的用于判斷錯(cuò)誤的值,但是ANSI C沒(méi)有提供其他可以表示錯(cuò)誤的值。因此對(duì)于這些函數(shù),在有些情況下需要先使用lua_is*系列函數(shù)判斷是否類型正確,而對(duì)于剩下的函數(shù),則可以直接通過(guò)判斷返回值是否為NULL即可。
    對(duì)于lua_tolstring函數(shù)返回的指向內(nèi)部字符串的指針,在該索引指向的元素被彈出之后,將無(wú)法保證仍然有效。該函數(shù)返回的字符串末尾均會(huì)有一個(gè)尾部0。
    下面將給出一個(gè)工具函數(shù),可用于演示上面提到的部分函數(shù),如:
復(fù)制代碼 代碼如下:

static void stackDump(lua_State* L)
{
    int top = lua_gettop(L);
    for (int i = 1; i <= top; ++i) {
        int t = lua_type(L,i);
        switch(t) {
        case LUA_TSTRING:
            printf("'%s'",lua_tostring(L,i));
            break;
        case LUA_TBOOLEAN:
            printf(lua_toboolean(L,i) ? "true" : "false");
            break;
        case LUA_TNUMBER:
            printf("%g",lua_tonumber(L,i));
            break;
        default:
            printf("%s",lua_typename(L,t));
            break;
        }
        printf("");
    }
    printf("/n");
}

 

  3). 其它棧操作函數(shù):

    除了上面給出的數(shù)據(jù)交換函數(shù)之外,Lua的C API還提供了一組用于操作虛擬棧的普通函數(shù),如:
 

復(fù)制代碼 代碼如下:

    int lua_gettop(lua_State* L); --返回棧中元素的個(gè)數(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); --刪除指定索引上的元素,其上面的元素自動(dòng)下移。
    void lua_insert(lua_State* L, int index); --將棧頂元素插入到該索引值指向的位置。
    void lua_replace(lua_State* L, int index); --彈出棧頂元素,并將該值設(shè)置到指定索引上。
 

    Lua還提供了一個(gè)宏用于彈出指定數(shù)量的元素:
復(fù)制代碼 代碼如下:
#define lua_pop(L,n)  lua_settop(L, -(n) - 1)   

    見(jiàn)如下示例代碼:
復(fù)制代碼 代碼如下:

int main()
{
    lua_State* L = luaL_newstate();
    lua_pushboolean(L,1);
    lua_pushnumber(L,10);
    lua_pushnil(L);
    lua_pushstring(L,"hello");
    stackDump(L); //true 10 nil 'hello'

 

    lua_pushvalue(L,-4);
    stackDump(L); //true 10 nil 'hello' true

    lua_replace(L,3);
    stackDump(L); //true 10 true 'hello'

    lua_settop(L,6);
    stackDump(L); //true 10 true 'hello' nil nil

    lua_remove(L,-3);
    stackDump(L); //true 10 true nil nil

    lua_settop(L,-5);
    stackDump(L); //true

    lua_close(L);
    return 0;
}

 

3. C API中的錯(cuò)誤處理:

    1). C程序調(diào)用Lua代碼的錯(cuò)誤處理:

    通常情況下,應(yīng)用程序代碼是以“無(wú)保護(hù)”模式運(yùn)行的。因此,當(dāng)Lua發(fā)現(xiàn)“內(nèi)存不足”這類錯(cuò)誤時(shí),只能通過(guò)調(diào)用“緊急”函數(shù)來(lái)通知C語(yǔ)言程序,之后在結(jié)束應(yīng)用程序。用戶可通過(guò)lua_atpanic來(lái)設(shè)置自己的“緊急”函數(shù)。如果希望應(yīng)用程序代碼在發(fā)生Lua錯(cuò)誤時(shí)不會(huì)退出,可通過(guò)調(diào)用lua_pcall函數(shù)以保護(hù)模式運(yùn)行Lua代碼。這樣再發(fā)生內(nèi)存錯(cuò)誤時(shí),lua_pcall會(huì)返回一個(gè)錯(cuò)誤代碼,并將解釋器重置為一致的狀態(tài)。如果要保護(hù)與Lua的C代碼,可以使用lua_cpall函數(shù),它將接受一個(gè)C函數(shù)作為參數(shù),然后調(diào)用這個(gè)C函數(shù)。
    
    2). Lua調(diào)用C程序:

    通常而言,當(dāng)一個(gè)被Lua調(diào)用的C函數(shù)檢測(cè)到錯(cuò)誤時(shí),它就應(yīng)該調(diào)用lua_error,該函數(shù)會(huì)清理Lua中所有需要清理的資源,然后跳轉(zhuǎn)回發(fā)起執(zhí)行的那個(gè)lua_pcall,并附上一條錯(cuò)誤信息。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院
欧美精品久久久久久久小说| 国产一区二区影视| 亚洲国产日韩在线人成电影| 狠狠综合久久久综合| 免费精品国产自产拍在| 狠狠操视频网| 国产麻豆麻豆| 永久免费av片在线观看全网站 | 欧美高清视频| 中文字幕免费在线视频| 国产91久久久久| 日本不卡影院| 国产一级在线观看| 99久热re在线精彩视频| 六月天色婷婷| 精品入口蜜桃| 欧美另类在线视频| 国产激情视频在线| 美女av在线播放| av手机天堂| 国产一二区视频| 免费国产阿v视频在线观看| 国产精品区一区二| 免费a在线看| 99热免费观看| 国产日产一区二区三区| 欧美婷婷久久五月精品三区| 国产成人久久精品77777| 免费影视观看网站入口| 国产aⅴ超薄肉色丝袜交足| 成 人免费视频播放| 国产桃色电影在线播放| 欧美啪啪精品| 日本片在线看| 日本欧洲一区| 日本免费视频www| av日韩国产| 99爱视频在线观看| 91在线最新| 精品久久亚洲一级α| 国产精品麻豆一区二区三区| 中文字幕在线免费观看| 国产在线www| 成人av小说网| 午夜国产在线| 国产高清在线| 国产激情自拍| 国产h在线观看| 精品视频二区三区| 在线视频婷婷| 麻豆网站在线免费观看| 国产专区在线播放| 国产美女在线一区二区三区| 欧美视频免费一区二区三区| 九九热免费视频| 国产你懂的在线观看| 最新av中文字幕| 2021天堂中文幕一二区在线观| 精品一二三区视频| 欧美在线中文| 国产一二三视频| 最好看更新中文字幕| 中文字幕高清av| 国产aa视频| 欧美日韩综合高清一区二区| 欧美成人精品福利网站| 国产理论在线观看| ·天天天天操| 成人免费一区二区三区牛牛| 国产极品视频| 久久五月精品| 国产福利在线视频| а√资源新版在线天堂| 最近高清中文在线字幕在线观看| 国产精品久久在线| 欧美视频免费一区二区三区| 国产小视频免费在线网址| 国产精品美女一区二区视频| 永久免费在线观看| 激情丁香婷婷| av网址在线免费观看| 国产一级视频| 欧美a免费在线| 天堂中文在线视频| 久久精品视频观看| 99在线播放| 国产天堂资源| 中文字幕免费中文| 懂色av中文在线| 久热中文字幕精品视频在线| 中文av资源在线| 国产日韩欧美第一页| 色综合久久五月天| 精品视频三区| 国产成人午夜精品| 国产精品冒白浆免费视频| www.色婷婷| 热99re久久精品精品免费| 伊人中文字幕在线| 91精品大全| 777电影在线观看| 国产精品爱久久久久久久小说| 免费精品国产自产拍观看| 99re6在线视频精品免费| 国产视频一二区| 国产精品一区牛牛影视| 九九免费视频| www.操.com| 日本高清不卡中文字幕 | 丁香婷婷激情| 午夜小视频在线| 日本综合一区二区三区| 亚洲视频手机在线观看| 在线视频中文字幕| 99热99re6国产在线播放| 国产95在线|亚洲| 2019中文字幕视频| 日韩黄色成人| 美女永久在线网站| 中文字幕久热在线精品| 国产在线中文字幕| 国产精品亚洲第五区在线| 国产深夜福利| 永久免费av网站| 激情四房婷婷| 精品偷拍激情视频在线观看| jizz亚洲大全| 国产精品冒白浆免费视频| 亚洲精品xxxxx| 中文字幕免费中文| 欧美专区日韩| 国产精彩视频在线观看免费蜜芽| 亚洲最新永久观看在线| 最新国产在线| jizz在线视频| 国产三区视频在线观看| 亚洲欧美小说国产图片| 国产免费专区| 天堂在线国产| 国产高清av| 国产在线观看91| 免费av不卡在线观看| 在线国产三级| 国产aⅴ超薄肉色丝袜交足| 福利在线国产| 欧美日韩亚洲第一页| 18激情网站| 国产极品一区二区三区 | 粉嫩av一区| av免费在线免费| 国产第一页在线| 国产视频三区| 国产精品视频一区二区三区麻豆 | 国产卡一卡二卡三| 青青草原国产在线| eeuss影院在线播放| 中文字幕2020第一页| 国产精品视频二区三区| 成人超碰在线| 国产在线一二| 高清欧美精品xxxxx在线看| 夜夜嗨yeyeh| 精品99又大又爽又硬少妇毛片| 国产视频一二区| 国产高清免费在线播放| 国产夫妻视频| 亚洲综合色视频在线观看| 天天插天天干| xxx国产精品| 久草亚洲一区| 国产一卡2卡3卡四卡网站| 中文字幕日本在线| 国产精品bbw一区二区三区| 国产精品免费视频二三区| 精品一区二区观看| 在线视频色在线| www久久日com| 国产免费黄网站| 国产精品久久久久久福利| 国产黄色在线| 伊人影院在线视频| 日本高清中文字幕| 国产毛片在线| 69久久久久| 成 人免费视频播放| 最近久乱中文字幕| 精品成人一区二区三区免费视频| 伊人久久青青草| 成人超碰在线| 精品一区二区三区在线观看l| 亚洲成a人v欧美综合天堂麻豆| wwww在线观看| 国产午夜在线视频| 四虎国产精品永久| 国产网站免费看| sese一区| 樱花草在线观看www| 国内外激情在线| 性色视频在线| 2020国产在线视频|