這是一個幾年前寫的對lua的訪問封裝,當時的項目僅提供了最基本的lua訪問接口:調用lua函數,向lua注冊標准格式的C++函數.
本來我想引進luabind,但luabind相對又過於復雜,並不是所有功能都是我需要的,並且還要為此引入龐大boost.最終還是決定
按需求編寫一個簡單的封裝庫.
首先簡單列一下我的需求:
1)可以注冊任意類型的C++函數到lua中
2)可以方便的調用lua函數,方便的訪問lua中的表
3)可以訪問lua中創建的對象,調用lua對象提供的方法
4)注冊C++類型到lua,使lua可以訪問C++對象的字段,和函數
下面介紹一下提供的一些API:
1)call_luaFunction,用於方便的調用lua函數,使用格式如下:
int ret = call_luaFunction<int>("funname",L);
2)register_function,用於向lua注冊任意類型的C++函數,例如有如下函數:
static int showmsg(const char *msg)
{
printf("%s\n",msg);
return 0;
}
則可以這樣注冊,register_function(L,"show",showmsg);3)register_class,register_property,register_member_function用於向lua注冊一個C++類型
4)luaObject,代表lua中的對象,可以通過成員函數CallMemberFunction,SetMemberValue,GetMemberValue
訪問lua對象的方法和成員變量
5)luatable,代表lua中的表
6)Interger64用以支持在lua中實現64位整型運算
這裡說明一下,我不想C++對象在lua中被創建,而只能在C++中創建再傳遞給lua(Interger64是個例外,因為它主要是在lua中被使用的類型),所以register_class
並沒有提供構造函數的注冊.
測試代碼:
1 #include "luaWrapper.h" 2 #include <stdio.h> 3 4 static int userdata(lua_State *L) 5 { 6 int *a = (int*)lua_touserdata(L,-1); 7 printf("a = %d\n",*a); 8 return 0; 9 } 10 static int showmsg(const char *msg) 11 { 12 printf("%s\n",msg); 13 return 0; 14 } 15 16 class testa 17 { 18 public: 19 int vala; 20 int valb[10]; 21 }; 22 23 class testd 24 { 25 public: 26 virtual void testdf(){} 27 int vald; 28 }; 29 30 class testb : virtual public testa,virtual public testd 31 { 32 public: 33 34 virtual void function() 35 { 36 printf("this is function\n"); 37 } 38 39 int64_t valb; 40 double vald; 41 }; 42 43 class testc : public testb 44 { 45 public: 46 void function() 47 { 48 printf("this is testc\n"); 49 } 50 51 void functionc() 52 { 53 printf("functionc\n"); 54 } 55 }; 56 57 int main() 58 { 59 luaWrapper lw; 60 lw.init(); 61 lw.load("start.lua"); 62 lua_State *L = *(&lw); 63 //測試注冊任意C++函數 64 register_function(L,"show",showmsg); 65 66 //測試向lua注冊C++類 67 register_class<testb>(L,"testb"); 68 register_property("valb",&testb::valb); 69 register_property("vald",&testb::vald); 70 register_member_function("func",&testb::function); 71 72 register_class<testc,testb>(L,"testc"); 73 register_member_function("funcc",&testc::functionc); 74 75 testc tc; 76 tc.valb = 1000000000000000002; 77 tc.vald = 10.0f; 78 testb tb; 79 tb.valb = 1000; 80 call_luaFunction<void>("test1",L,&tc,(int64_t)1000000000000000001); 81 printf("%lld\n",tc.valb); 82 printf("%f\n",tc.vald); 83 84 luatable ret = call_luaFunction<luatable>("test2",L); 85 int i=0; 86 printf("{"); 87 for(;i<ret.size();++i) 88 { 89 printf("%d,",any_cast<int>(ret[i])); 90 } 91 printf("}\n"); 92 93 lua_results<5> ret1 = call_luaFunction<lua_results<5>>("test4",L); 94 printf("{"); 95 for(i=0;i<ret1._rets.size();++i) 96 { 97 printf("%d,",any_cast<int>(ret1._rets[i])); 98 } 99 printf("}\n"); 100 101 luaObject ac = call_luaFunction<luaObject>("test3",L); 102 ac.CallMemberFunction<void>("show"); 103 printf("balance:%d\n",ac.GetMemberValue<int>("balance")); 104 ac.SetMemberValue<int>("balance",1000); 105 printf("balance:%d\n",ac.GetMemberValue<int>("balance")); 106 luatable lt_in; 107 for(int i = 0; i < 5;++i) 108 lt_in.push_back(i); 109 call_luaFunction<void>("test5",L,lt_in); 110 111 call_luaFunction<void>("test6",L,"this is string"); 112 113 lt_in.clear(); 114 lt_in.push_back((const char*)"hello1"); 115 lt_in.push_back((const char*)"hello2"); 116 lt_in.push_back((const char*)"hello3"); 117 lt_in.push_back((const char*)"hello4"); 118 lt_in.push_back((const char*)"hello5"); 119 call_luaFunction<void>("test5",L,lt_in); 120 getchar(); 121 return 0; 122 }
1 Account = { 2 balance = 10, 3 names=0, 4 } 5 6 7 function Account:withdraw (v) 8 self.balance = self.balance - v 9 end 10 11 function Account:new (o) 12 o = o or {} 13 setmetatable(o, self) 14 self.__index = self 15 return o 16 end 17 18 function Account:show() 19 print("this is account show") 20 end 21 22 function Account:getBalance() 23 return self.balance 24 end 25 26 function Account:setBalance(val) 27 self.balance = val 28 end 29 30 function t(tb) 31 tb:func() 32 end 33 34 function test1(tb,i) 35 t(tb) 36 show("hello world") 37 print(tb.valb) 38 tb.valb = i64:new(10000003) 39 tb.vald = 1000.2 40 print(i) 41 end 42 43 function test2() 44 return {1,2,3,4,5} 45 end 46 47 function test3() 48 account = Account:new(); 49 account.balance = 100 50 account.name = "sniperHW" 51 return account 52 end 53 54 function test4() 55 return 1,2,3,4,5 56 end 57 58 function test5(lt) 59 print(lt[1]) 60 print(lt[2]) 61 print(lt[3]) 62 print(lt[4]) 63 print(lt[5]) 64 end 65 66 function test6(str) 67 print(str) 68 end
跟C放在同一個目錄下就好了
如果工程在編譯的話 放到工程文件夾裡
如果是編譯好了 要脫離編譯器運行了 就放到exe同目錄下就好
前提是你在調用lua文件的時候是直接使用文件名
如果有需要放目錄裡 路徑加上就好 反正是從當前目錄開始計算
調用的時候
lua_pcall四個參數意義你都知道吧
第一個是堆棧
然後是參數個數
再然後返回值
最後錯誤處理函數
所以只要把lua_pcall(L, 2, 1, 0);改成lua_pcall(L, n, 1, 0);
通過控制變量n來控制就好了
再者 以後發代碼好好斷行 不然別人看的很辛苦
material_print = print
function funky_print (...)
for i=1, arg.n do
material_print("lua: " .. arg[i])
end
end
funky_print("aa","bb","cc")