Skip to content

Commit e6d1445

Browse files
authored
commit lua_visitor.cpp
1 parent c4df0fa commit e6d1445

File tree

1 file changed

+342
-0
lines changed

1 file changed

+342
-0
lines changed

lua_visitor.cpp

+342
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
2+
#include <iostream>
3+
#include <cassert>
4+
#include <tuple>
5+
#include <functional>
6+
7+
extern "C"
8+
{
9+
#include "lua/lua.h"
10+
#include "lua/lualib.h"
11+
#include "lua/lauxlib.h"
12+
#include "lua/lundump.h"
13+
}
14+
15+
16+
17+
18+
namespace LuaVisitor
19+
{
20+
21+
template<class T> void LuaPushObj(lua_State *L, T const &t)
22+
{
23+
assert(false);
24+
}
25+
template<> void LuaPushObj(lua_State *L, int const &t)
26+
{
27+
lua_pushinteger(L, t);
28+
}
29+
template<> void LuaPushObj(lua_State *L, long long const &t)
30+
{
31+
lua_pushinteger(L, ptrdiff_t(t));
32+
}
33+
template<> void LuaPushObj(lua_State *L, double const &t)
34+
{
35+
lua_pushnumber(L, t);
36+
}
37+
template<> void LuaPushObj(lua_State *L, char const *const &t)
38+
{
39+
lua_pushstring(L, t);
40+
}
41+
template<> void LuaPushObj(lua_State *L, std::string const &t)
42+
{
43+
lua_pushstring(L, t.c_str());
44+
}
45+
template<> void LuaPushObj(lua_State *L, bool const &t)
46+
{
47+
lua_pushboolean(L, t);
48+
}
49+
50+
51+
template<class T> T LuaGetObj(lua_State *L, int index)
52+
{
53+
assert(false);
54+
}
55+
template<> int LuaGetObj(lua_State *L, int index)
56+
{
57+
return int(lua_tointeger(L, index));
58+
}
59+
template<> long long LuaGetObj(lua_State *L, int index)
60+
{
61+
return (long long)(lua_tointeger(L, index));
62+
}
63+
template<> double LuaGetObj(lua_State *L, int index)
64+
{
65+
return double(lua_tonumber(L, index));
66+
}
67+
template<> float LuaGetObj(lua_State *L, int index)
68+
{
69+
return float(lua_tonumber(L, index));
70+
}
71+
template<> char const *LuaGetObj(lua_State *L, int index)
72+
{
73+
return lua_tostring(L, index);
74+
}
75+
template<> std::string LuaGetObj(lua_State *L, int index)
76+
{
77+
return lua_tostring(L, index);
78+
}
79+
template<> bool LuaGetObj(lua_State *L, int index)
80+
{
81+
return lua_toboolean(L, index);
82+
}
83+
84+
85+
86+
template<size_t ...I>
87+
struct LuaIndexes
88+
{
89+
};
90+
template<size_t S, size_t ...I>
91+
struct LuaMakeIndexes
92+
{
93+
typedef typename LuaMakeIndexes<S - 1, I..., sizeof...(I)>::indexes indexes;
94+
};
95+
template<size_t ... I>
96+
struct LuaMakeIndexes<0, I...>
97+
{
98+
typedef LuaIndexes<I...> indexes;
99+
};
100+
101+
template<class ...P, size_t ...I> int LuaMultiRuturn(lua_State *L, std::tuple<P...> &&result, LuaIndexes<I...>)
102+
{
103+
std::initializer_list<int>({ (LuaPushObj(L, std::get<I>(result)), 0)... });
104+
return sizeof...(P);
105+
}
106+
template<class R> int LuaRuturn(lua_State *L, R &&result)
107+
{
108+
LuaPushObj(L, std::forward<R>(result));
109+
return 1;
110+
}
111+
template<class ...P> int LuaRuturn(lua_State *L, std::tuple<P...> &&result)
112+
{
113+
typedef typename LuaMakeIndexes<sizeof...(P)>::indexes indexes;
114+
return LuaMultiRuturn(L, std::move(result), indexes());
115+
}
116+
117+
template<class ...P>
118+
struct LuaResult
119+
{
120+
typedef std::tuple<typename std::decay<P>::type...> type;
121+
};
122+
template<class ...P>
123+
struct LuaResult<LuaResult<P...>>
124+
{
125+
typedef typename LuaResult<P...>::type type;
126+
};
127+
template<class T>
128+
struct LuaResult<T>
129+
{
130+
typedef typename std::decay<T>::type type;
131+
};
132+
133+
template<class R, class ... P, size_t ...I>
134+
int LuaCallBack(lua_State *L, LuaIndexes<I...>, R (*f)(P...))
135+
{
136+
return LuaRuturn(L, f(LuaGetObj<P>(L, I + 1)...));
137+
}
138+
template<class R, class ... P, size_t ...I>
139+
int LuaCallBack(lua_State *L, LuaIndexes<I...>, std::function<R(P...)> const &f)
140+
{
141+
return LuaRuturn(L, f(LuaGetObj<P>(L, I + 1)...));
142+
}
143+
template<class ... P, size_t ...I>
144+
int LuaCallBack(lua_State *L, LuaIndexes<I...>, void (*f)(P...))
145+
{
146+
f(LuaGetObj<P>(L, I + 1)...);
147+
return 0;
148+
}
149+
template<class ... P, size_t ...I>
150+
int LuaCallBack(lua_State *L, LuaIndexes<I...>, std::function<void(P...)> const &f)
151+
{
152+
f(LuaGetObj<P>(L, I + 1)...);
153+
return 0;
154+
}
155+
156+
template<class ...P>
157+
std::tuple<typename std::decay<P>::type...> LuaTable(P &&...p)
158+
{
159+
return std::tuple<typename std::decay<P>::type...>(std::forward<P>(p)...);
160+
};
161+
template<class T> void LuaGetTable(lua_State *L, T &&t)
162+
{
163+
LuaPushObj(L, std::forward<T>(t));
164+
lua_gettable(L, -2);
165+
}
166+
167+
template<class ...P, size_t ...I> void LuaCallGetTable(lua_State *L, LuaIndexes<I...>, std::tuple<P...> const &table)
168+
{
169+
std::initializer_list<int>({ (LuaGetTable(L, std::get<I + 1>(table)), 0)... });
170+
}
171+
template<class ...P, size_t ...I> std::tuple<P...> LuaCallGetResult(lua_State *L, LuaIndexes<I...>)
172+
{
173+
return {LuaGetObj<P>(L, int(I) - int(sizeof...(P)))...};
174+
}
175+
176+
template<class T, int N, int M> struct LuaGetResult
177+
{
178+
T operator()(lua_State *L)
179+
{
180+
lua_call(L, N, 1);
181+
auto result = LuaGetObj<T>(L, -1);
182+
lua_pop(L, M + 1);
183+
return result;
184+
}
185+
};
186+
template<class ...P, int N, int M> struct LuaGetResult<LuaResult<P...>, N, M>
187+
{
188+
std::tuple<typename std::decay<P>::type...> operator()(lua_State *L)
189+
{
190+
typedef typename LuaMakeIndexes<sizeof...(P)>::indexes indexes;
191+
lua_call(L, N, sizeof...(P));
192+
auto result = LuaCallGetResult<typename std::decay<P>::type...>(L, indexes());
193+
lua_pop(L, M + int(sizeof...(P)));
194+
return result;
195+
}
196+
};
197+
template<int N, int M> struct LuaGetResult<void, N, M>
198+
{
199+
void operator()(lua_State *L)
200+
{
201+
lua_call(L, N, 0);
202+
if(M > 0)
203+
{
204+
lua_pop(L, M);
205+
}
206+
}
207+
};
208+
209+
struct LuaObject
210+
{
211+
void *obj;
212+
char const *name;
213+
};
214+
215+
216+
template<class R, class ...P>
217+
typename LuaResult<R>::type LuaCallFunction(lua_State *L, char const *func, P &&...p)
218+
{
219+
lua_getglobal(L, func);
220+
std::initializer_list<int>({ (LuaPushObj(L, std::forward<P>(p)), 0)... });
221+
return LuaGetResult<R, sizeof...(P), 0>()(L);
222+
}
223+
template<class R, class ...P, class ...T>
224+
typename LuaResult<R>::type LuaCallFunction(lua_State *L, std::tuple<T...> const &func, P &&...p)
225+
{
226+
typedef typename LuaMakeIndexes<sizeof...(T) - 1>::indexes indexes;
227+
lua_getglobal(L, std::get<0>(func));
228+
LuaCallGetTable(L, indexes(), func);
229+
std::initializer_list<int>({ (LuaPushObj(L, std::forward<P>(p)), 0)... });
230+
return LuaGetResult<R, sizeof...(P), sizeof...(T) - 1>()(L);
231+
}
232+
template<class R, class ...P>
233+
void LuaRegFunction(lua_State *L, char const *func, R (*f)(P...))
234+
{
235+
struct handler
236+
{
237+
static int invoke(lua_State *L)
238+
{
239+
typedef typename LuaMakeIndexes<sizeof...(P)>::indexes indexes;
240+
R (*callback)(P...) = reinterpret_cast<R (*)(P...)>(lua_touserdata(L, lua_upvalueindex(1)));
241+
return LuaCallBack(L, indexes(), callback);
242+
}
243+
};
244+
lua_pushlightuserdata(L, reinterpret_cast<void *>(f));
245+
lua_pushcclosure(L, handler::invoke, 1);
246+
lua_setglobal(L, func);
247+
}
248+
249+
}
250+
251+
using LuaVisitor::LuaTable;
252+
using LuaVisitor::LuaResult;
253+
using LuaVisitor::LuaRegFunction;
254+
using LuaVisitor::LuaCallFunction;
255+
256+
257+
int foo(int a, int b)
258+
{
259+
return a + b;
260+
}
261+
std::tuple<int, int> bar(int a, int b, int c)
262+
{
263+
return {a + b + c + 100, 100};
264+
}
265+
int call_count = 0;
266+
void asd()
267+
{
268+
++call_count;
269+
}
270+
271+
272+
void test_lua(int count)
273+
{
274+
lua_State *L = luaL_newstate();
275+
luaopen_base(L);
276+
luaopen_table(L);
277+
luaopen_io(L);
278+
luaopen_string(L);
279+
luaopen_math(L);
280+
281+
LuaRegFunction(L, "foo", foo);
282+
LuaRegFunction(L, "bar", bar);
283+
LuaRegFunction(L, "asd", asd);
284+
285+
luaL_dostring(L, R"(
286+
ttt = {};
287+
ttt[1] = {};
288+
local ccc = ttt[1];
289+
ccc.run = function(num)
290+
return 1, num, "foo";
291+
end
292+
293+
function test(count)
294+
local sum = 0, i;
295+
for i = 0, count - 1, 1 do
296+
sum = sum + foo(0, i);
297+
local r1, r2 = bar(1, i, -1);
298+
sum = sum + r1 - r2;
299+
asd();
300+
end
301+
return sum;
302+
end
303+
)");
304+
305+
LuaCallFunction<void>(L, "test", 10);
306+
std::cout << LuaCallFunction<long long>(L, "test", count) << std::endl;
307+
auto ret = LuaCallFunction<LuaResult<int, int, std::string>>(L, LuaTable("ttt", 1, "run"), 666);
308+
std::cout << std::get<0>(ret) << std::endl;
309+
std::cout << std::get<1>(ret) << std::endl;
310+
std::cout << std::get<2>(ret) << std::endl;
311+
312+
std::cout << call_count << std::endl;
313+
314+
lua_close(L);
315+
}
316+
317+
struct scope_timer
318+
{
319+
std::string msg;
320+
std::chrono::high_resolution_clock::time_point pt;
321+
template<class T>
322+
scope_timer(T &&t) : msg(std::forward<T>(t)), pt(std::chrono::high_resolution_clock::now())
323+
{
324+
}
325+
~scope_timer()
326+
{
327+
using namespace std::chrono;
328+
std::cout
329+
<< msg
330+
<< " "
331+
<< duration_cast<duration<float, std::milli>>(high_resolution_clock::now() - pt).count()
332+
<< std::endl;
333+
}
334+
};
335+
336+
int main()
337+
{
338+
scope_timer st("lua");
339+
test_lua(1000000);
340+
return 0;
341+
}
342+

0 commit comments

Comments
 (0)