亚洲综合原千岁中文字幕_国产精品99久久久久久久vr_无码人妻aⅴ一区二区三区浪潮_成人h动漫精品一区二区三

主頁 > 知識庫 > Lua教程(十七):C API簡介

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

熱門標簽:陜西便宜電銷機器人軟件 衡水外呼線路解決 昆明電話外呼系統好么 艾比利外呼系統 電話機器人每天搜索多少次 免費門店地圖標注注冊入駐 杞縣地圖標注app 海口智能語音電銷機器人好用嗎 外呼系統一天耗費多少流量

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

1. 基礎知識:

C API是一組能使C/C++代碼與Lua交互的函數。其中包括讀寫Lua全局變量、調用Lua函數、運行一段Lua代碼,以及注冊C函數以供Lua代碼調用等。這里先給出一個簡單的示例代碼:

復制代碼 代碼如下:

#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;
}


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

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

    2. 棧:

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

    1). 壓入元素:

    Lua針對每種C類型,都有一個C API函數與之對應,如:
 

復制代碼 代碼如下:

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

    對于字符串數據,Lua不會持有他們的指針,而是調用在API時生成一個內部副本,因此,即使在這些函數返回后立刻釋放或修改這些字符串指針,也不會有任何問題。
    在向棧中壓入數據時,可以通過調用下面的函數判斷是否有足夠的棧空間可用,一般而言,Lua會預留20個槽位,對于普通應用來說已經足夠了,除非是遇到有很多參數的函數。
    int lua_checkstack(lua_State* L, int extra) --期望得到extra數量的空閑槽位,如果不能擴展并獲得,返回false。 
    
    2). 查詢元素:

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

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

復制代碼 代碼如下:

    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);
 

    以上函數,成功返回1,否則返回0。需要特別指出的是,對于lua_isnumber而言,不會檢查值是否為數字類型,而是檢查值是否能轉換為數字類型。
    Lua還提供了一個函數lua_type,用于獲取元素的類型,函數原型如下:
 
復制代碼 代碼如下:

    int lua_type (lua_State *L, int index);
 

    該函數的返回值為一組常量值,分別是:LUA_TNIL、LUA_TNUMBER、LUA_TBOOLEAN、LUA_TSTRING、LUA_TTABLE、LUA_TFUNCTION、LUA_TUSERDATA、LUA_TTHREAD和LUA_TLIGHTUSERDATA。這些常量通常用于switch語句中。
    除了上述函數之外,Lua還提供了一組轉換函數,如:
 
復制代碼 代碼如下:

    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類型返回操作符'#'等同的結果,userdata類型返回分配的內存塊長度。
    size_t lua_objlen (lua_State *L, int index); 
 

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

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). 其它棧操作函數:

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

復制代碼 代碼如下:

    int lua_gettop(lua_State* L); --返回棧中元素的個數。
    void lua_settop(lua_State* L, int index); --將棧頂設置為指定的索引值。
    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); --彈出棧頂元素,并將該值設置到指定索引上。
 

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

    見如下示例代碼:
復制代碼 代碼如下:

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中的錯誤處理:

    1). C程序調用Lua代碼的錯誤處理:

    通常情況下,應用程序代碼是以“無保護”模式運行的。因此,當Lua發現“內存不足”這類錯誤時,只能通過調用“緊急”函數來通知C語言程序,之后在結束應用程序。用戶可通過lua_atpanic來設置自己的“緊急”函數。如果希望應用程序代碼在發生Lua錯誤時不會退出,可通過調用lua_pcall函數以保護模式運行Lua代碼。這樣再發生內存錯誤時,lua_pcall會返回一個錯誤代碼,并將解釋器重置為一致的狀態。如果要保護與Lua的C代碼,可以使用lua_cpall函數,它將接受一個C函數作為參數,然后調用這個C函數。
    
    2). Lua調用C程序:

    通常而言,當一個被Lua調用的C函數檢測到錯誤時,它就應該調用lua_error,該函數會清理Lua中所有需要清理的資源,然后跳轉回發起執行的那個lua_pcall,并附上一條錯誤信息。

您可能感興趣的文章:
  • Lua教程(一):簡介、優勢和應用場景介紹
  • Lua教程(二):基礎知識、類型與值介紹
  • Lua教程(三):表達式和語句
  • Lua教程(四):函數詳解
  • Lua教程(五):迭代器和泛型for
  • Lua教程(六):編譯執行與錯誤
  • Lua教程(七):數據結構詳解
  • Lua教程(八):數據持久化
  • Lua教程(九):元表與元方法詳解
  • Lua教程(十): 全局變量和非全局的環境
  • Lua教程(十一):模塊與包詳解
  • Lua教程(十二):面向對象編程
  • Lua教程(十三):弱引用table
  • Lua教程(十四):字符串庫詳解
  • Lua教程(十五):輸入輸出庫(I/O庫)

標簽:泰安 南京 海口 臨滄 宿遷 昌都 西寧 營口

巨人網絡通訊聲明:本文標題《Lua教程(十七):C API簡介》,本文關鍵詞  Lua,教程,十七,API,簡介,Lua,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Lua教程(十七):C API簡介》相關的同類信息!
  • 本頁收集關于Lua教程(十七):C API簡介的相關信息資訊供網民參考!
  • 推薦文章
    午夜精品国产自在现线拍| 高清一级片| 青草国产在线| 国产国语在线播放视频| 麻豆系列国产剧在线观看| 亚洲 欧美 91| 日韩中文字幕在线观看视频| 国产视频久久久| 国产成人欧美一区二区三区的| 99色播| 久草免费在线观看| 欧美国产日韩一区二区三区| 美女免费黄网站| 999久久66久6只有精品| 国产91视频网| 亚久久伊人精品青青草原2020| 欧美激情中文字幕一区二区| 日韩在线观看网站| 亚洲第一色在线| 天堂网中文字幕| 国产一级强片在线观看| 精品视频一区二区三区免费| 一本高清在线| 成人影院一区二区三区| 精品视频在线观看免费| 欧美另类videosbestsex高清| 欧美a免费| 久草免费在线视频| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 国产精品1024在线永久免费| 天天做日日爱| a级毛片免费观看网站| 超级乱淫伦动漫| 久久99中文字幕久久| 免费的黄色小视频| 国产网站免费观看| 国产视频一区二区三区四区 | 日本伦理片网站| 国产亚洲免费观看| 欧美a免费| 美女免费精品视频在线观看| 美女免费精品高清毛片在线视 | 欧美a级片免费看| 日韩免费在线视频| 国产麻豆精品hdvideoss| 999久久久免费精品国产牛牛| 成人免费网站视频ww| 国产一区二区精品久久91| 国产精品免费精品自在线观看| 成人a大片在线观看| 亚洲第一色在线| 国产麻豆精品高清在线播放| 国产高清在线精品一区a| 国产原创中文字幕| 久久久成人影院| 色综合久久手机在线| 99久久精品国产高清一区二区| 国产一区免费在线观看| 九九干| 免费国产在线观看| 日韩一级精品视频在线观看| 色综合久久手机在线| 九九干| 成人影视在线播放| 国产不卡在线播放| 亚洲女初尝黑人巨高清在线观看| 国产成a人片在线观看视频| 亚州视频一区二区| 欧美激情影院| 精品久久久久久中文| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 台湾毛片| 日韩一级黄色| 亚洲第一页色| 精品视频一区二区三区| 午夜在线影院| 国产一级生活片| 韩国毛片免费大片| 日韩专区第一页| 99久久网站| 韩国三级一区| 免费的黄色小视频| 久久精品道一区二区三区| 美女被草网站| 国产不卡在线观看视频| 欧美1区| 韩国毛片免费大片| 国产a视频| 国产一区免费在线观看| 色综合久久天天综线观看| 麻豆系列 在线视频| 午夜在线观看视频免费 成人| 欧美a免费| 成人免费观看网欧美片| 国产极品白嫩美女在线观看看| 一级片片| 久久成人综合网| 黄视频网站在线看| 欧美激情一区二区三区中文字幕| 国产福利免费视频| 日韩综合| 青青青草视频在线观看| 99热精品一区| 亚欧成人毛片一区二区三区四区| 毛片电影网| 国产不卡在线看| 国产视频一区二区在线观看| 91麻豆国产级在线| 亚飞与亚基在线观看| 国产视频一区二区在线播放| 欧美一级视频免费观看| 国产一区二区精品久久91| 99热精品一区| 国产a视频| 国产麻豆精品| 欧美a级大片| 欧美a免费| 青青久在线视频| 国产成人精品综合久久久| 久久国产精品自由自在| 四虎影视久久久| 韩国三级视频网站| 尤物视频网站在线| 国产网站免费视频| 人人干人人草| 国产一区二区福利久久| 日韩在线观看视频黄| 日韩免费在线观看视频| 久草免费在线色站| 四虎论坛| 天天做日日干| 韩国三级香港三级日本三级| 日韩在线观看网站| 日韩中文字幕一区| 超级乱淫黄漫画免费| 天堂网中文字幕| 国产一区二区福利久久| 成人免费观看视频| 久久精品免视看国产成人2021| 97视频免费在线| 日韩一级精品视频在线观看| 欧美国产日韩久久久| 成人a级高清视频在线观看| 午夜在线亚洲| 香蕉视频三级| 韩国三级视频网站| 欧美激情一区二区三区视频 | 国产一区二区福利久久| 99久久精品国产麻豆| 韩国三级香港三级日本三级la| 国产一区二区精品久久91| 麻豆系列 在线视频| 天天色色色| 日本免费看视频| 亚洲精品久久玖玖玖玖| 国产极品白嫩美女在线观看看| 欧美a免费| 精品久久久久久中文字幕一区| 国产精品自拍一区| 成人影院一区二区三区| 亚洲女人国产香蕉久久精品| 精品国产一区二区三区免费| 国产91视频网| 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 成人免费网站视频ww| 91麻豆国产级在线| 黄色免费网站在线| 欧美大片aaaa一级毛片| 超级乱淫黄漫画免费| 亚洲第一页色| 欧美爱色| 中文字幕一区二区三区精彩视频| 日韩欧美一及在线播放| 久久久成人网| 国产欧美精品午夜在线播放| 精品国产一区二区三区国产馆| 免费国产一级特黄aa大片在线| 国产精品免费精品自在线观看| 九九干| 欧美日本二区| 国产极品白嫩美女在线观看看| 天天做日日爱夜夜爽| 日韩专区第一页| 久久精品欧美一区二区| 中文字幕97| 人人干人人草| 日日日夜夜操| 毛片成人永久免费视频| 亚洲第一页色| 亚洲天堂在线播放| 999久久久免费精品国产牛牛| 国产不卡福利| 久久成人亚洲| 欧美国产日韩久久久| 国产网站免费观看| 韩国三级视频网站| 国产一区国产二区国产三区| 亚洲天堂免费观看| 色综合久久天天综合| 午夜家庭影院|