欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Lua和C++語言的交互詳解

 更新時間:2014年09月30日 10:00:52   作者:果凍想  
這篇文章主要介紹了Lua和C++語言的交互詳解,本文講解了C++和Lua交互,涉及到獲取Lua中普通變量的值,Lua中table的值和調用Lua中的函數(shù),需要的朋友可以參考下

前言

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

Lua的一項重要用途就是作為一種配置語言。而這篇文章將結合Lua來擴展應用程序,這種方式提供了更大的靈活性和便利性。

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

從一個最簡單的例子開始

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

復制代碼 代碼如下:

bool CLuaConfig::LoadConfig()
{
    L = luaL_newstate();
    if (!L)
    {
        return false;
    }
 
    // 加載配置文件
    int bRet = luaL_loadfile(L, pConfigFile);
    if (bRet)
    {
        return false;
    }
    // 運行配置文件
    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就不說了,用爛了;luaL_loadfile用于加載一個lua文件,然后調用lua_pcall運行編譯好的程序塊,lua_pcall是在保護模式下運行Lua代碼,也就是說,出錯了,lua_pcall會返回一個錯誤代碼,并不會直接crash。當運行完程序塊后,調用了兩次lua_getglobal函數(shù),這個函數(shù)會將全局變量值壓入棧中,所以,width的值在索引為-2的位置,height的值在索引為-1的位置;接下來,就不用多說了。就是這樣。下載程序,運行一下,就OK了,修改代碼文件夾下的config.lua文件,看看運行結果。源代碼這里下載。

table操作

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

復制代碼 代碼如下:

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

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

復制代碼 代碼如下:

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

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

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

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

復制代碼 代碼如下:

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

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

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

2.lua_setfield函數(shù)同lua_getfield是一個性質的函數(shù),只不過這里是set語義,將lua_push*到棧中的值,設置到table對應的key中。

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

復制代碼 代碼如下:

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

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

調用Lua函數(shù)

是的,你沒有看錯,你可以在一lua文件中定義一個函數(shù),然后在C++中調用這個函數(shù),貌似“高大上”的感覺?,F(xiàn)在我就來說說這個“高大上”的功能;習慣性的上代碼:

復制代碼 代碼如下:

// 再來看看有參數(shù)和返回值得函數(shù)調用
// 現(xiàn)在在test.lua中定義了一個add函數(shù),計算兩個值的和,這兩個值就是用參數(shù)傳進去的
// 得到和以后,會返回這個和,現(xiàn)在我們就在C++這邊調用這個add函數(shù)
lua_getglobal(L, "add"); // 獲取函數(shù),壓入棧中
lua_pushnumber(L, 10); // 壓入第一個參數(shù)
lua_pushnumber(L, 20); // 壓入第二個參數(shù)
 
// 完成調用
iRet = lua_pcall(L, 2, 1, 0);
if (iRet)
{
    const char *pErrorMsg = lua_tostring(L, -1);
    cout << pErrorMsg << endl;
    lua_close(L);
    return 0;
}
 
// 獲得計算結果
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;

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

復制代碼 代碼如下:

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

這個簡單的Lua函數(shù)沒有任何講的地方,說說上面的那一長段C++代碼吧。在Lua中,函數(shù)和普通的值是一樣的,所以,C++調用Lua中的函數(shù),分為以下幾步:

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

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

這些準備工作都準備就緒以后,就調用lua_pcall開始調用函數(shù)了,調用完成以后,會將返回值壓入棧中;

最后取返回值得過程不用多說了,調用完畢。

源代碼這里下載。

總結

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

相關文章

  • Lua中的協(xié)同程序之resume-yield間的數(shù)據(jù)返回研究

    Lua中的協(xié)同程序之resume-yield間的數(shù)據(jù)返回研究

    這篇文章主要介紹了Lua中的協(xié)同程序之resume-yield間的數(shù)據(jù)返回研究本文講解了resume的參數(shù)、resume函數(shù)的第二個返回值、yield的返回值等內(nèi)容,需要的朋友可以參考下
    2014-09-09
  • Lua極簡入門指南(一):函數(shù)篇

    Lua極簡入門指南(一):函數(shù)篇

    這篇文章主要介紹了Lua極簡入門指南(一):函數(shù)篇,本文講解了函數(shù)的定義、函數(shù)多值返回、變長參數(shù)、閉包(closures)等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • 淺析Lua中的迭代器

    淺析Lua中的迭代器

    這篇文章主要介紹了Lua中的迭代器,是Lua入門學習中的基礎知識,需要的朋友可以參考下
    2015-05-05
  • Lua中訪問table里函數(shù)的方法示例

    Lua中訪問table里函數(shù)的方法示例

    這篇文章主要介紹了Lua中訪問table里函數(shù)的方法示例,本文例子超級簡單,算是入門實例吧,其實只需要表名.方法名即可訪問,重要的還是其它代碼寫法,本文給出了一個完整的代碼示例,需要的朋友可以參考下
    2015-04-04
  • Lua面向對象編程之基礎結構table簡例

    Lua面向對象編程之基礎結構table簡例

    今天小編就為大家分享一篇關于Lua面向對象編程之基礎結構table簡例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • Lua編程中使用嵌套循環(huán)的使用教程

    Lua編程中使用嵌套循環(huán)的使用教程

    這篇文章主要介紹了Lua編程中使用嵌套循環(huán)的使用教程,是Lua入門學習中的基礎知識,需要的朋友可以參考下
    2015-05-05
  • Lua獲取文件長度和判斷文件是否存在函數(shù)分享

    Lua獲取文件長度和判斷文件是否存在函數(shù)分享

    這篇文章主要介紹了Lua獲取文件長度和判斷文件是否存在函數(shù)分享,需要的朋友可以參考下
    2015-04-04
  • 詳解Lua中的元表概念

    詳解Lua中的元表概念

    這篇文章主要介紹了詳解Lua中的元表,是Lua入門學習中的基礎知識,需要的朋友可以參考下
    2015-05-05
  • Lua的迭代器使用中應該避免的問題和技巧

    Lua的迭代器使用中應該避免的問題和技巧

    這篇文章主要介紹了Lua的迭代器使用中應該避免的問題和技巧,本文介紹了避免創(chuàng)建閉合函數(shù)、利用恒定狀態(tài)創(chuàng)造更多變量、不需要for循環(huán)的迭代器等內(nèi)容,需要的朋友可以參考下
    2014-09-09
  • Lua腳本實現(xiàn)遞歸刪除一個文件夾

    Lua腳本實現(xiàn)遞歸刪除一個文件夾

    這篇文章主要介紹了Lua腳本實現(xiàn)遞歸刪除一個文件夾,本文給出了C++和Lua兩個版本的實現(xiàn)代碼,需要的朋友可以參考下
    2015-05-05

最新評論