這是我的Lua系列教程的第二篇,本篇文章主要介紹C++和Lua相互傳遞數(shù)據(jù)。如果你還不知道怎么在c/c++里面調用Lua腳本的話,請參考這篇文章. 本文主要介紹基本數(shù)據(jù)類型的傳遞,比如整形(int),字符串(string)、數(shù)字(number)及bool值。
加載并運行Lua腳本
由于在上一個教程里面已經介紹過如何在C/C++里面嵌入Lua,所以這一節(jié)就簡單的介紹一下程序怎么用,配置就略過啦。
創(chuàng)建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來執(zhí)行Lua腳本。
C/C++調用Lua函數(shù)
首先,我們在hello.lua里面定義一個lua函數(shù):
復制代碼 代碼如下:
-- add two numbers
function add ( x, y )
return x + y
end
Lua的函數(shù)定義是以function為keyword,然后以end結尾,同時它的參數(shù)是沒有形參類型的,另外,Lua的函數(shù)可以返回多個值。不過我們這里只返回了一個值。
接下來,讓我們看看如果在C++程序里面調用這個函數(shù):
復制代碼 代碼如下:
int luaAdd(lua_State *lua_state , int x, int y)
{
int sum;
//獲取lua里面的add函數(shù)并把它放到lua的棧頂
lua_getglobal(lua_state, "add");
//往lua棧里面壓入兩個參數(shù)
lua_pushnumber(lua_state, x);
lua_pushnumber(lua_state, y);
//調用lua函數(shù),這里的2是參數(shù)的個數(shù),1是返回值的個數(shù)
lua_call(lua_state, 2, 1);
//從棧頂讀取返回值,注意這里的參數(shù)是-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: "mynamestd::endl;
這一次我們又是通過lua_getglobal來把myname這個全局變量壓到lua棧,然后用lua_tostring來取這個值。
C++里面修改Lua全局變量的值
這次我們使用的是lua_setglobal來傳遞數(shù)據(jù)給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++里面是倒過來的。因為我們是使用棧作為數(shù)據(jù)結構來傳遞數(shù)據(jù),而棧是先進后出的。
下一篇文章,我們將介紹一下C++調用Lua的Table。
您可能感興趣的文章:- Lua教程(五):C/C++操作Lua數(shù)組和字符串示例
- Lua教程(四):在Lua中調用C語言、C++的函數(shù)
- Lua教程(三):C語言、C++中調用Lua的Table示例
- Lua教程(一):在C++中嵌入Lua腳本
- Lua教程(六):綁定一個簡單的C++類