1柜裸、交互原理
一個(gè)Lua程序與C的交互都是通過(guò)Lua虛擬機(jī)中的一個(gè)堆棧進(jìn)行的缕陕,通過(guò)調(diào)用Lua C API可以讓C中的值入棧再出棧賦值給Lua ,也可以讓Lua值入棧再出棧賦給C疙挺。
Lua的8種基本類型:nill扛邑、boolean、number铐然、string蔬崩、userdata、function锦爵、thread舱殿、table,? Lua C API 都提供相應(yīng)的操作接口。
Lua C API 具體閱讀lua.h险掀、lualib.h沪袭、lauxlib.h頭文件。
2、一些基礎(chǔ)概念
?? Lua_State ?? :? 一個(gè)Lua_State管理著Lua虛擬機(jī)的一個(gè)執(zhí)行環(huán)境冈绊,擁有獨(dú)立的數(shù)據(jù)棧和調(diào)用棧幻妓,表示一個(gè)Lua程序的執(zhí)行狀態(tài)灵临。
?Lua虛擬棧: lua虛擬機(jī)中的用來(lái)實(shí)現(xiàn)lua與C交互的棧济竹,棧都是先進(jìn)后出的惋啃,我們對(duì)棧的操作都是基于棧頂?shù)模簿褪钦f(shuō)如果要獲取到棧底元素毅该,需要將其上面的依次彈出博秫。虛擬棧的索引方式有兩種,正索引和負(fù)索引眶掌,正索引(1-N)挡育, 負(fù)索引((-N)-(-1))。
3朴爬、訪問(wèn)Lua變量實(shí)現(xiàn)
??我這邊使用的是vs建立的c++工程即寒。
?新建一個(gè)main.lua文件,并敲入如下代碼:
?var1 = 5
print(“this is in lua \n”)
在C++源文件中,先導(dǎo)入需要的頭文件: ?
#include? <windows.h> ? ?? //系統(tǒng)的頭文件召噩,我們?cè)诤竺鏁?huì)用到一個(gè)系統(tǒng)的方法需要
extern "C" {
? #include <lua.h>
?#include <lualib.h>
? #inlude <lauxlib.h>
}
定義一個(gè)獲取lua變量的函數(shù):
void get_luaVar(lua_State *L){
? ? ? ? int ?? lua_var;
? ? ? ? lua_getglobal(L, "var1"); ? ? ? ? ? ? ? ? ? ?? //從lua變量空間將var1變量放入棧中
? ? ?? if (!lua_isnumber(L, -1)) ? ? ? ? ? ? ? ? ? ? ?? // 通常需要對(duì)棧中元素類型做下檢測(cè)
? ? ?? printf("is not number");
? ? ?? lua_var = lua_tonumber(L, -1); ? ? ? // 從棧中讀取剛才壓入的變量母赵,此時(shí)并不會(huì)將變量出棧
? ? ?? printf("讀取lua中var1變量的值? %d\n\n", lua_var);
}
定義一個(gè)設(shè)置lua變量的函數(shù):
void set_luaVar(lua_State *L){
? ? ?? lua_pushinteger(L, 100) ; ?? //將100壓入棧中
? ? ?? lua_setglobal(L, "var1"); ? //將剛壓入棧中值出棧并賦值給lua全局變量
? ? ? printf("為lua變量var1賦值100 ? \n\n");
}
在入口函數(shù)處加載Lua文件,并調(diào)用以上函數(shù):
int _tmain(int argc, _TCHAR* argv[]){
? ? ? ? lua_State *L = luaL_newstate(); ? ? ? ? ?? // 創(chuàng)建一個(gè)Lua執(zhí)行環(huán)境
? ? ? ? luaL_openlibs(L); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //打開(kāi)Lua庫(kù)
? ? ?? luaL_dofile(L, "main.lua"); ? ? ? ? ? ? ?? // 加載并執(zhí)行main.lua文件
? ? ?? get_luaVar(L); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? //獲取lua變量
? ? ?? set_luaVar(L); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //設(shè)置lua變量
? ? ?? get_luaVar(L); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //再獲取lua變量
? ? ?? lua_close(L); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //關(guān)閉lua執(zhí)行環(huán)境
? ? ?? system("pause"); ? ? ? ? ? ? ? ? ? ? ? ? ? ?? // 暫停windows輸出窗口具滴,方便查看輸出
? ? ?? return 0;
}
運(yùn)行程序得到如下打影汲啊:
this is in lua
讀取lua中var1變量的值? 5
為lua變量var1賦值100
讀取lua中var1變量的值? 100
請(qǐng)按任意鍵繼續(xù). . .
實(shí)現(xiàn)了對(duì)lua變量的賦值和讀取。
4抵蚊、查看虛擬棧中的值
? 在lua與C的交互中施绎,有些API將值從棧中彈出溯革,有的只是讀取里面的值不會(huì)將值從棧中彈出贞绳,如上面使用的lua_tonumber()這類API,?還有的不是將值而是將指針?lè)湃霔V兄孪 _@些需要平時(shí)總結(jié)下規(guī)律去熟練冈闭。這里介紹官方提供的一個(gè)方法,可以實(shí)時(shí)查看當(dāng)前堆棧的里面的值抖单。
static void stackDump(lua_State *L) {
? ?? int i;
? ? int top = lua_gettop(L); /* depth of the stack */
? ? for (i = 1; i <= top; i++) { /* repeat for each level */
? ? int t = lua_type(L, i);
? ? switch (t) {
? ? ?? case LUA_TSTRING: { /* strings */
? ? ? ? ? ? printf("'%s'", lua_tostring(L, i));
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? case LUA_TBOOLEAN: { /* Booleans */
? ? ? ? ?? printf(lua_toboolean(L, i) ? "true" : "false");
? ? ? ? ?? break;
? ? ? ? }
? ? ?? case LUA_TNUMBER: { /* numbers */
? ? ? ? ?? printf("%g", lua_tonumber(L, i));
? ? ? ? ?? break;
? ? ? }
? ? ?? default: { /* other values */
? ? ? ? ?? printf("%s", lua_typename(L, t));
? ? ? ? ? break;
? ? ? }
? ?? }
? ? ?? printf(" "); /* put a separator */
?? }
?? printf("\n"); /* end the listing */
}
在你想要查看當(dāng)前堆棧里面有什么值時(shí),調(diào)用stackDump()即可萎攒。