-
Notifications
You must be signed in to change notification settings - Fork 0
/
cfunction.hpp
86 lines (71 loc) · 2.93 KB
/
cfunction.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#pragma once
#include "util.hpp"
namespace glua {
template<typename FunctionT, FunctionT func>
class cfunction {};
template<typename Ret, typename... Args, Ret(*func)(Args...)>
class cfunction<Ret(*)(Args...), func> {
public:
using func_type = decltype(func);
using return_type = typename function_traits<func_type>::return_type;
using argument_types = typename function_traits<func_type>::argument_types;
static inline int wrapper(lua_State* l) {
return_type val = call_with_tuple(func, api::checkGet<argument_types>(*l));
api::clearStack(*l);
api::push<Ret>(*l, val);
return function_traits<func_type>::nrets;
}
};
template<typename Ret, typename C, typename... Args, Ret(C::*func)(Args...)>
class cfunction<Ret(C::*)(Args...), func> {
public:
using func_type = decltype(func);
using return_type = typename function_traits<func_type>::return_type;
using argument_types = typename function_traits<func_type>::argument_types;
static inline int wrapper(lua_State* l) {
return_type val = call_with_tuple(func, api::checkGet<argument_types>(*l));
api::clearStack(*l);
api::push<Ret>(*l, val);
return function_traits<func_type>::nrets;
}
};
template<typename Functor, bool = std::is_same<typename function_traits<Functor>::return_type, void>::value>
class cfunctor {};
template<typename Functor>
class cfunctor<Functor, false> {
public:
using func_type = Functor;
using return_type = typename function_traits<func_type>::return_type;
using argument_types = typename function_traits<func_type>::argument_types;
static inline void push(lua_State& l, Functor f) {
func_type& func = api::newUserdata<func_type>(l, "functor");
new (&func) func_type(f);
lua_pushcclosure(&l, &wrapper, 1);
}
static inline int wrapper(lua_State* l) {
func_type& func = api::getUserdata<func_type>(*l, api::upvalueIndex(1), "functor");
return_type val = call_with_tuple(func, api::checkGet<argument_types>(*l));
api::clearStack(*l);
api::push<return_type>(*l, val);
return function_traits<func_type>::nrets;
}
};
template<typename Functor>
class cfunctor<Functor, true> {
public:
using func_type = Functor;
using return_type = typename function_traits<func_type>::return_type;
using argument_types = typename function_traits<func_type>::argument_types;
static inline void push(lua_State& l, Functor f) {
func_type& func = api::newUserdata<func_type>(l, "functor");
new (&func) func_type(f);
lua_pushcclosure(&l, &wrapper, 1);
}
static inline int wrapper(lua_State* l) {
func_type& func = api::getUserdata<func_type>(*l, api::upvalueIndex(1), "functor");
call_with_tuple(func, api::checkGet<argument_types>(*l));
api::clearStack(*l);
return function_traits<func_type>::nrets;
}
};
} // namespace glua