這是一個幾年前寫的對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")