Lua教程(二):C++和Lua相互傳遞資料樣本_Lua

來源:互聯網
上載者:User

這是我的Lua系列教程的第二篇,本篇文章主要介紹C++和Lua相互傳遞資料。如果你還不知道怎麼在c/c++裡面調用Lua指令碼的話,請參考這篇文章. 本文主要介紹基礎資料型別 (Elementary Data Type)的傳遞,比如整形(int),字串(string)、數字(number)及bool值。

載入並運行Lua指令碼

由於在上一個教程裡面已經介紹過如何在C/C++裡面嵌入Lua,所以這一節就簡單的介紹一下程式怎麼用,配置就略過啦。

建立Lua虛擬機器

複製代碼 代碼如下:

lua_State *lua_state = luaL_newstate();

載入Lua庫

複製代碼 代碼如下:

static const luaL_Reg lualibs[] =
    {
        {"base", luaopen_base},
        {"io", luaopen_io},
        {NULL, NULL}
    };
    const luaL_Reg *lib = lualibs;
    for(; lib->func != NULL; lib++)
    {
        luaL_requiref(lua_state, lib->name, lib->func, 1);
        lua_pop(lua_state,1);
    }

運行Lua指令碼

複製代碼 代碼如下:

std::string scriptPath = FileUtils::getInstance()->fullPathForFilename("hello.lua");
int status = luaL_loadfile(lua_state, scriptPath.c_str());
std::cout << " return: " << status << std::endl;
int result = 0;
if(status == LUA_OK)
{
    result = lua_pcall(lua_state, 0, LUA_MULTRET, 0);
}
else
{
    std::cout << " Could not load the script." << std::endl;
}

這裡我們使用的是luaL_loadfile而不是之前的luaL_dofile,其實luaL_dofile只是一個宏定義:

複製代碼 代碼如下:

#define luaL_dofile(L, fn) \
    (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))

我們先調用luaL_loadfile可以判斷Lua指令碼是否載入成功,然後再調用lua_pcall來執行Lua指令碼。

C/C++調用Lua函數

首先,我們在hello.lua裡面定義一個lua函數:

複製代碼 代碼如下:

-- add two numbers
function add ( x, y )
    return x + y
end

Lua的函數定義是以function為keyword,然後以end結尾,同時它的參數是沒有形參類型的,另外,Lua的函數可以返回多個值。不過我們這裡只返回了一個值。

接下來,讓我們看看如果在C++程式裡面調用這個函數:

複製代碼 代碼如下:

int luaAdd(lua_State *lua_state , int x, int y)
{
    int sum;
    //擷取lua裡面的add函數並把它放到lua的棧頂
    lua_getglobal(lua_state, "add");
    //往lua棧裡面壓入兩個參數
    lua_pushnumber(lua_state, x);
    lua_pushnumber(lua_state, y);
    //調用lua函數,這裡的2是參數的個數,1是傳回值的個數
    lua_call(lua_state, 2, 1);
    //從棧頂讀取傳回值,注意這裡的參數是-1
    sum = lua_tointeger(lua_state, -1);
    //最後我們把傳回值從棧頂拿掉
    lua_pop(lua_state, 1);
    return sum;
}

然後,我們就可以在程式裡面調用它了:

複製代碼 代碼如下:

std::cout<< "2 + 1= " << luaAdd(lua_state,4,1)<<std::endl;

注意這個方法調用要在lua_pcall調用之後。

操作Lua全域變數

C++裡面擷取Lua全域變數的值

首先,我們在hello.lua裡面定義一個全域變數

複製代碼 代碼如下:

myname = "子龍山人"

然後我們在C++裡面訪問它:

複製代碼 代碼如下:

lua_getglobal(lua_state, "myname");
std::string myname = lua_tostring(lua_state, -1);
lua_pop(lua_state, 1);
std::cout<<"Hello: "<<myname<<std::endl;

這一次我們又是通過lua_getglobal來把myname這個全域變數壓到lua棧,然後用lua_tostring來取這個值。

C++裡面修改Lua全域變數的值

這次我們使用的是lua_setglobal來傳遞資料給Lua:

複製代碼 代碼如下:

lua_pushstring(lua_state, "World");
    lua_setglobal(lua_state, "myname");

這時,我們只要在hello.lua的最開始部分,調用print(myname)就可以列印傳遞進來的值了。

C++傳遞Table給Lua

複製代碼 代碼如下:

lua_createtable(lua_state, 2, 0);
    lua_pushnumber(lua_state, 1);
    lua_pushnumber(lua_state, 49);
//    lua_settable(lua_state, -3);
    lua_rawset(lua_state, -3);
    lua_pushnumber(lua_state, 2);
    lua_pushstring(lua_state, "Life is a beach");
//    lua_settable(lua_state, -3);
    lua_rawset(lua_state, -3);
    lua_setglobal(lua_state, "arg");

這裡我們傳遞了一個table給lua,這個table為{49,”Life is a beach”}。Lua table的索引是從1開始的,然後我們在lua指令碼裡面可以這樣子來訪問這個table:

複製代碼 代碼如下:

for i=1,#arg do
    print("      ", i, arg[i])
end

這裡的#arg是獲得table的長度,然後使用arg[i]來擷取table的索引i處的value。

Lua返回多個值給C++

首先是Lua代碼:

複製代碼 代碼如下:

local temp = {9, "hehehej"}
-- temp[1]=9
-- temp[2]="See you space cowboy!"
return temp,9,1

然後是C++代碼:

複製代碼 代碼如下:

std::stringstream str_buf;
    while(lua_gettop(lua_state))
    {
        str_buf.str(std::string());
        str_buf << " ";
        switch(lua_type(lua_state, lua_gettop(lua_state)))
        {
            case LUA_TNUMBER:
                str_buf << "script returned the number: "
                << lua_tonumber(lua_state, lua_gettop(lua_state));
                break;
            case LUA_TTABLE:
                str_buf << "script returned a table";
                break;
            case LUA_TSTRING:
                str_buf << "script returned the string: "
                << lua_tostring(lua_state, lua_gettop(lua_state));
                break;
            case LUA_TBOOLEAN:
                str_buf << "script returned the boolean: "
                << lua_toboolean(lua_state, lua_gettop(lua_state));
                break;
            default:
                str_buf << "script returned an unknown-type value";
        }
        lua_pop(lua_state, 1);
        std::cout << str_buf.str() << std::endl;
    }

最後輸出結果為:

複製代碼 代碼如下:

[C++] Values returned from the script:
 script returned the number: 1
 script returned the number: 9
 script returned a table
[C++] Closing the Lua state

在lua裡面return值的順序是table,9,1,而在C++裡面是倒過來的。因為我們是使用棧作為資料結構來傳遞資料,而棧是先進後出的。

下一篇文章,我們將介紹一下C++調用Lua的Table。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.