這是一個幾年前寫的對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;
}
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
並沒有提供構造函數的注冊.
測試代碼:
#include "luaWrapper.h" #include <stdio.h> static int userdata(lua_State *L) { int *a = (int*)lua_touserdata(L,-1); printf("a = %d\n",*a); return 0; } static int showmsg(const char *msg) { printf("%s\n",msg); return 0; } class testa { public: int vala; int valb[10]; }; class testd { public: virtual void testdf(){} int vald; }; class testb : virtual public testa,virtual public testd { public: virtual void function() { printf("this is function\n"); } int64_t valb; double vald; }; class testc : public testb { public: void function() { printf("this is testc\n"); } void functionc() { printf("functionc\n"); } }; int main() { luaWrapper lw; lw.init(); lw.load("start.lua"); lua_State *L = *(&lw); //測試注冊任意C++函數 register_function(L,"show",showmsg); //測試向lua注冊C++類 register_class<testb>(L,"testb"); register_property("valb",&testb::valb); register_property("vald",&testb::vald); register_member_function("func",&testb::function); register_class<testc,testb>(L,"testc"); register_member_function("funcc",&testc::functionc); testc tc; tc.valb = 1000000000000000002; tc.vald = 10.0f; testb tb; tb.valb = 1000; call_luaFunction<void>("test1",L,&tc,(int64_t)1000000000000000001); printf("%lld\n",tc.valb); printf("%f\n",tc.vald); luatable ret = call_luaFunction<luatable>("test2",L); int i=0; printf("{"); for(;i<ret.size();++i) { printf("%d,",any_cast<int>(ret[i])); } printf("}\n"); lua_results<5> ret1 = call_luaFunction<lua_results<5>>("test4",L); printf("{"); for(i=0;i<ret1._rets.size();++i) { printf("%d,",any_cast<int>(ret1._rets[i])); } printf("}\n"); luaObject ac = call_luaFunction<luaObject>("test3",L); ac.CallMemberFunction<void>("show"); printf("balance:%d\n",ac.GetMemberValue<int>("balance")); ac.SetMemberValue<int>("balance",1000); printf("balance:%d\n",ac.GetMemberValue<int>("balance")); luatable lt_in; for(int i = 0; i < 5;++i) lt_in.push_back(i); call_luaFunction<void>("test5",L,lt_in); call_luaFunction<void>("test6",L,"this is string"); lt_in.clear(); lt_in.push_back((const char*)"hello1"); lt_in.push_back((const char*)"hello2"); lt_in.push_back((const char*)"hello3"); lt_in.push_back((const char*)"hello4"); lt_in.push_back((const char*)"hello5"); call_luaFunction<void>("test5",L,lt_in); getchar(); return 0; }
Account = { balance = 10, names=0, } function Account:withdraw (v) self.balance = self.balance - v end function Account:new (o) o = o or {} setmetatable(o, self) self.__index = self return o end function Account:show() print("this is account show") end function Account:getBalance() return self.balance end function Account:setBalance(val) self.balance = val end function t(tb) tb:func() end function test1(tb,i) t(tb) show("hello world") print(tb.valb) tb.valb = i64:new(10000003) tb.vald = 1000.2 print(i) end function test2() return {1,2,3,4,5} end function test3() account = Account:new(); account.balance = 100 account.name = "sniperHW" return account end function test4() return 1,2,3,4,5 end function test5(lt) print(lt[1]) print(lt[2]) print(lt[3]) print(lt[4]) print(lt[5]) end function test6(str) print(str) end
源代碼地址:
