1、首先說下目的,為什么要這么做 ?
在此之前,如果不知道C和lua怎么進行數據交互的童鞋,請移步另一篇文章《Linux下C/C++和lua交互-Table》。
正式項目中,希望主程序盡量不做修改,於是使用C/C++完成功能的主干(即不需要經常變動的部分)用lua這類輕量級的解釋性語言實現一些存在不確定性的功能邏輯;所以,程序功能如有問題,只需對lua腳本作出修改,而修改腳本的好處是簡單高效,改完腳本后重新執行程序便能看到效果。
2、具體怎么做?
一般來說,C/C++調用lua接口或是數據交互,首先要做的是包含lua相關操作的頭文件以及lua庫相關的頭文件,然后調用接口創建lua環境、用操作棧的規則和lua交互數據或參數(調用lua函數);執行所需操作或是取得所需數據后銷毀lua環境。以下用源碼進行詳細解釋:
①、C++源文件
1 //1、包含頭文件 2 extern "C" 3 { 4 #include<lua5.2/lua.h> 5 #include<lua5.2/lauxlib.h> 6 #include<lua5.2/lualib.h> 7 } 8 //2、創建lua環境 9 lua_State *L = luaL_newstate(); 10 if(L == NULL) 11 { 12 cout<<"Creat Lua State Error !"<<endl; 13 return 1; 14 } 15 //如需在終端輸出打印信息,庫是必須加載的,否則看不到lua的print信息 16 luaL_openlibs(L); 17 //3、加載lua腳本 18 const string lua_path = "../scripts/"; 19 const string file = "Function.lua"; 20 string script = lua_path + file ; 21 int ret = luaL_dofile(L ,script.c_str()); 22 if(ret) 23 { 24 cout<<"Lua doFile Error !"<<endl; 25 return 1; 26 } 27 //4、調用腳本中已寫好的函數 28 //a、無參函數 29 lua_getglobal(L, "ruler"); //函數名為ruler 30 lua_pcall(L,0,0,0); //用保護模式調用lua函數,入參個數為0、出參個數為0、無自定義錯誤處理 31 32 //b、有參函數 33 lua_getglobal(L, "add"); //函數名為add 34 lua_pushnumber(L, number1); //第一個入參 35 lua_pushnumber(L, number2); //第二個入參 36 lua_pcall(L,2,1,0); //函數有兩個入參,一個出參,所以函數形式為add(a,b) 37 //5、獲得返回值,單回值情況下調用完成后lua會把結果放到棧頂,多返回值時,按照規則存放,具體查API 38 if(lua_isnumber(L,-1)) 39 { 40 cout<<"the result is :"<<lua_tonumber(L,-1)<<endl; 41 } 42 //6、銷毀lua環境 43 lua_close(L);
②、lua腳本
1 //7、add,lua腳本內容 2 function add(a,b) 3 return a+b; 4 end 5 6 function ruler() 7 print("this is some thing need to tell you !!!"); 8 end
3、結語:
總之,lua和C/C++交互必須依靠媒介——棧;用lua作為配置文件時,內容為靜態的,組織為table,C++通過table相關接口操作數據;當用lua作為較為復雜的函數語言時,當前lua中所有全局函數都可以被宿主語言調用,且如果要用lua輸出打印信息以便調試,此時必須open lua庫,否則將看不到print相關內容,且全局的print都會導致difile()失敗。
典型操作就這兩類,其余的,都可以通過查閱API手冊嘗試去使用,have fun !