主頁(yè) > 知識(shí)庫(kù) > Lua和C++語(yǔ)言的交互詳解

Lua和C++語(yǔ)言的交互詳解

熱門(mén)標(biāo)簽:400手機(jī)電話免費(fèi)辦理 智能語(yǔ)音電銷(xiāo)的機(jī)器人 如何利用高德地圖標(biāo)注家 上海企業(yè)外呼系統(tǒng)排名 武漢百應(yīng)人工智能電銷(xiāo)機(jī)器人 揚(yáng)州電銷(xiāo)外呼系統(tǒng)軟件 電腦外呼系統(tǒng)輻射大嗎 開(kāi)通400電話申請(qǐng)流程 百度地圖標(biāo)注位置網(wǎng)站

前言

寫(xiě)過(guò)Windows程序的人都知道,對(duì)于應(yīng)用程序,如果需要在本地保存一些配置信息,我們經(jīng)常將這些配置信息寫(xiě)在注冊(cè)表或者本地的配置文件中,很多應(yīng)用都是將一些配置信息寫(xiě)在配置文件中,比如以ini結(jié)尾的文件,這種配置文件很多,使用的很廣泛,然后應(yīng)用程序在啟動(dòng)的時(shí)候,就會(huì)解析這個(gè)配置文件,讀取一些配置信息。

Lua的一項(xiàng)重要用途就是作為一種配置語(yǔ)言。而這篇文章將結(jié)合Lua來(lái)擴(kuò)展應(yīng)用程序,這種方式提供了更大的靈活性和便利性。

這篇博文主要總結(jié)的是使用C++和Lua進(jìn)行交互,涉及到獲取Lua中普通變量的值,Lua中table的值和調(diào)用Lua中的函數(shù)。下面就開(kāi)始吧。

從一個(gè)最簡(jiǎn)單的例子開(kāi)始

一個(gè)GUI程序,從配置文件讀取窗口的大小,從而實(shí)現(xiàn)設(shè)置窗口的大小。下面我就寫(xiě)一個(gè)基于MFC的窗體程序來(lái)完成這個(gè)功能。點(diǎn)擊這里去下載完成代碼工程。我把重點(diǎn)的代碼貼出來(lái):

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

bool CLuaConfig::LoadConfig()
{
    L = luaL_newstate();
    if (!L)
    {
        return false;
    }
 
    // 加載配置文件
    int bRet = luaL_loadfile(L, pConfigFile);
    if (bRet)
    {
        return false;
    }
    // 運(yùn)行配置文件
    bRet = lua_pcall(L, 0, 0, 0);
    if (bRet)
    {
        return false;
    }
 
    // 讀取高
    lua_getglobal(L, "width");
    lua_getglobal(L, "height");
 
    // width
    if (!lua_isnumber(L, -2))
    {
        return false;
    }
 
    // height
    if (!lua_isnumber(L, -1))
    {
        return false;
    }
    iWindowHeight = lua_tointeger(L, -1);
    iWindowWidth = lua_tointeger(L, -2);
    return true;
}

luaL_newstate就不說(shuō)了,用爛了;luaL_loadfile用于加載一個(gè)lua文件,然后調(diào)用lua_pcall運(yùn)行編譯好的程序塊,lua_pcall是在保護(hù)模式下運(yùn)行Lua代碼,也就是說(shuō),出錯(cuò)了,lua_pcall會(huì)返回一個(gè)錯(cuò)誤代碼,并不會(huì)直接crash。當(dāng)運(yùn)行完程序塊后,調(diào)用了兩次lua_getglobal函數(shù),這個(gè)函數(shù)會(huì)將全局變量值壓入棧中,所以,width的值在索引為-2的位置,height的值在索引為-1的位置;接下來(lái),就不用多說(shuō)了。就是這樣。下載程序,運(yùn)行一下,就OK了,修改代碼文件夾下的config.lua文件,看看運(yùn)行結(jié)果。源代碼這里下載。

table操作

在Lua中,對(duì)于table這種bug一樣存在的東西,如果C API無(wú)法操作table,那我們還能不能愉快的玩耍了。讓我們來(lái)看看C API如何操作table?,F(xiàn)在有如下Lua語(yǔ)句:

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

background = {r = 0.3, g = 1, b = 0.5}

那么,C API如何讀取這段代碼,將其中的每個(gè)字段都解析出來(lái)呢。我先把代碼貼上來(lái),然后一句一句的分析:

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

// 讀取全局的數(shù)據(jù)到棧中
lua_getglobal(L, "background");
if (!lua_istable(L, -1))
{
    // 如果不是table,就顯示錯(cuò)誤信息
    cout "It's not a table." endl;
    return 0;
}
 
// 讀取table中字段的值,將值壓入棧中
lua_getfield(L, -1, "r");
 
// 讀取棧中的值
if (!lua_isnumber(L, -1))
{
    // 如果不是實(shí)數(shù),就顯示錯(cuò)誤信息
    cout "It's not a number." endl;
    return 0;
}
 
double fValue = lua_tonumber(L, -1);
cout "r => " fValue endl;

原諒我省略了luaL_newstate這樣的代碼。好了,讀取一個(gè)table,同讀取一個(gè)全局的變量是一個(gè)道理的。分為以下幾步:

1.使用lua_getglobal讀取這個(gè)變量,將table讀取到棧中;
2.使用lua_getfield讀取table中字段的值,將字段的值讀取到棧中;
3.使用lua_to*系列函數(shù),將字段的值從棧中讀取出來(lái)。

這是讀取table的操作,那設(shè)置table的操作呢?我們可以將我們自己的值寫(xiě)入到棧中,這該怎么操作?看代碼:

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

// 將需要設(shè)置的值設(shè)置到棧中
lua_pushnumber(L, 0.55);
 
// 將這個(gè)值設(shè)置到table中
lua_setfield(L, -2, "r");

就是上面兩行代碼,當(dāng)然了,你也需要先使用lua_getglobal讀取table變量,將table讀取到棧中,然后按照上面的兩行代碼進(jìn)行設(shè)置就OK了。上面兩行代碼的具體含義是什么呢?

1.lua_push*系列函數(shù)是將一個(gè)需要設(shè)置的新值放到棧中;

2.lua_setfield函數(shù)同lua_getfield是一個(gè)性質(zhì)的函數(shù),只不過(guò)這里是set語(yǔ)義,將lua_push*到棧中的值,設(shè)置到table對(duì)應(yīng)的key中。

現(xiàn)在讀取table,設(shè)置table都說(shuō)了,那如何在表中完全創(chuàng)建一個(gè)新的table呢?我們有這種需求。怎么辦?

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

// 創(chuàng)建一個(gè)新的table,并壓入棧
lua_newtable(L);
 
// 往table中設(shè)置值
lua_pushstring(L, "https://www.jb51.net"); // 先將值壓入棧
lua_setfield(L, -2, "website"); // 將值設(shè)置到table中
 
// 再設(shè)置一個(gè)值
lua_pushstring(L, "果凍想 | 一個(gè)原創(chuàng)文章分享網(wǎng)站");
lua_setfield(L, -2, "description");

我將重要的幾行代碼貼上來(lái)了,最重要的就是一個(gè)lua_newtable函數(shù),該函數(shù)會(huì)創(chuàng)建一個(gè)新的table,并將這個(gè)table置于棧中,接下來(lái)就和上面設(shè)置table的值是一樣的。源代碼下載一、下載二。 

調(diào)用Lua函數(shù)

是的,你沒(méi)有看錯(cuò),你可以在一lua文件中定義一個(gè)函數(shù),然后在C++中調(diào)用這個(gè)函數(shù),貌似“高大上”的感覺(jué)?,F(xiàn)在我就來(lái)說(shuō)說(shuō)這個(gè)“高大上”的功能;習(xí)慣性的上代碼:

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

// 再來(lái)看看有參數(shù)和返回值得函數(shù)調(diào)用
// 現(xiàn)在在test.lua中定義了一個(gè)add函數(shù),計(jì)算兩個(gè)值的和,這兩個(gè)值就是用參數(shù)傳進(jìn)去的
// 得到和以后,會(huì)返回這個(gè)和,現(xiàn)在我們就在C++這邊調(diào)用這個(gè)add函數(shù)
lua_getglobal(L, "add"); // 獲取函數(shù),壓入棧中
lua_pushnumber(L, 10); // 壓入第一個(gè)參數(shù)
lua_pushnumber(L, 20); // 壓入第二個(gè)參數(shù)
 
// 完成調(diào)用
iRet = lua_pcall(L, 2, 1, 0);
if (iRet)
{
    const char *pErrorMsg = lua_tostring(L, -1);
    cout pErrorMsg endl;
    lua_close(L);
    return 0;
}
 
// 獲得計(jì)算結(jié)果
iRet = lua_isnumber(L, -1);
if (!iRet)
{
    cout "Error occured." endl;
    lua_close(L);
    return 0;
}
 
double fValue = lua_tonumber(L, -1);
cout "Result is " fValue endl;

上面代碼是調(diào)用以下lua函數(shù):

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

-- 有參數(shù),有返回值
function add(iA, iB)
    return iA + iB
end

這個(gè)簡(jiǎn)單的Lua函數(shù)沒(méi)有任何講的地方,說(shuō)說(shuō)上面的那一長(zhǎng)段C++代碼吧。在Lua中,函數(shù)和普通的值是一樣的,所以,C++調(diào)用Lua中的函數(shù),分為以下幾步:

使用lua_getglobal來(lái)獲取函數(shù),然后將其壓入棧;

如果這個(gè)函數(shù)有參數(shù)的話,就需要依次將函數(shù)的參數(shù)也壓入棧;

這些準(zhǔn)備工作都準(zhǔn)備就緒以后,就調(diào)用lua_pcall開(kāi)始調(diào)用函數(shù)了,調(diào)用完成以后,會(huì)將返回值壓入棧中;

最后取返回值得過(guò)程不用多說(shuō)了,調(diào)用完畢。

源代碼這里下載。

總結(jié)

到此這篇文章總結(jié)完畢,總共花費(fèi)4天的業(yè)余的零碎時(shí)間,時(shí)間主要花費(fèi)在demo的編寫(xiě)上,好了,這篇文章獻(xiàn)上,希望對(duì)大家有幫助。如果你覺(jué)的還不錯(cuò),可以將這篇文章分享給更多的朋友。當(dāng)然了,你也可以掃描頁(yè)面右側(cè)的二維碼資助我寫(xiě)出更好的文章了,那定是極好的。

您可能感興趣的文章:
  • Lua和C/C++互相調(diào)用實(shí)例分析
  • C++利用LuaIntf調(diào)用Lua的方法示例
  • Lua中調(diào)用C++函數(shù)示例
  • 使用Lua來(lái)擴(kuò)展C++程序的方法
  • 把Lua函數(shù)傳遞到C/C++中實(shí)例
  • C++與Lua交互原理實(shí)例詳解

標(biāo)簽:宜賓 張掖 新余 嘉峪關(guān) 武漢 延邊 黑龍江 江西

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Lua和C++語(yǔ)言的交互詳解》,本文關(guān)鍵詞  Lua,和,C++,語(yǔ)言,的,交互,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Lua和C++語(yǔ)言的交互詳解》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于Lua和C++語(yǔ)言的交互詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章