/
lua_runtime.h
175 lines (159 loc) · 4.95 KB
/
lua_runtime.h
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#if !defined(AFX_LUARUNTIME_H__5E316F4C_EE73_4483_B0F0_6619A9D7C653__INCLUDED_)
#define AFX_LUARUNTIME_H__5E316F4C_EE73_4483_B0F0_6619A9D7C653__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <lua.hpp>
//extern int CollectTraceback(lua_State* L); // función para obtener stacktraces cuando hay errores
template <typename TBase>
class CLuaRuntime
{
public:
CLuaRuntime() : m_owner(true), m_error_handler(LUA_NOREF) {
m_L = lua_open();
if(m_L) {
static_cast<TBase*>(this)->Initialize();
}
}
CLuaRuntime(lua_State* L) : m_owner(false) {
m_L = L;
}
virtual ~CLuaRuntime() {
if(m_owner) {
lua_close(m_L);
}
}
protected:
// por defecto, abre todas las librerías
void Initialize() {
luaL_openlibs(m_L);
};
// por defecto, manda el string de error a la consola
int OnError() {
const char* strErr = lua_tostring(m_L, -1);
fprintf(stderr, "%s", strErr);
return 0;
};
public:
inline operator lua_State* () const { return m_L; };
inline int loadstring(const char* s) {
int iRet = luaL_loadstring(m_L, s);
if(iRet != 0) {
TBase* pT = static_cast<TBase*>(this);
pT->OnError(false);
}
return iRet;
}
inline int dostring(const char* s, int params = 0) {
int base = lua_gettop(m_L) - params; /* index of arguments*/
int iRet = luaL_loadstring(m_L, s);
if(iRet == 0) {
lua_insert(m_L, base + 1); /* move chunk below arguments */
pushErrorHandler(); /* push traceback function */
lua_insert(m_L, base + 1); /* put it under chunk and args */
iRet = lua_pcall(m_L, params, LUA_MULTRET, base + 1);
if(iRet != 0) {
TBase* pT = static_cast<TBase*>(this);
pT->OnError(true); // ya obtuve un stack trace, no intentar obtener uno porque no va a existir
}
lua_remove(m_L, base + 1); /* remove traceback function */
}
else {
TBase* pT = static_cast<TBase*>(this);
pT->OnError(false);
lua_pop(m_L, params);
}
return iRet;
}
inline int dofile(const char* filename) {
int iRet = luaL_loadfile(m_L, filename);
if(iRet == 0) {
int base = lua_gettop(m_L); /* function index */
pushErrorHandler(); /* push traceback function */
lua_insert(m_L, base); /* put it under chunk and args */
iRet = lua_pcall(m_L, 0, LUA_MULTRET, base);
if(iRet != 0) {
TBase* pT = static_cast<TBase*>(this);
pT->OnError(true); // ya obtuve un stack trace, no intentar obtener uno porque no va a existir
}
lua_remove(m_L, base); /* remove traceback function */
}
else {
TBase* pT = static_cast<TBase*>(this);
pT->OnError(false);
}
return iRet;
}
inline int loadfile(const char* filename) {
int iRet = luaL_loadfile(m_L, filename);
if(iRet != 0) {
TBase* pT = static_cast<TBase*>(this);
pT->OnError(false);
}
return iRet;
}
// sets the error handler we'll use
void setErrorHandler(int reference) {
m_error_handler = reference;
}
// pushes the error handler on the stack
void pushErrorHandler() {
if(m_error_handler != LUA_NOREF) {
lua_rawgeti(m_L, LUA_REGISTRYINDEX, m_error_handler);
}
else {
lua_getfield(m_L, LUA_GLOBALSINDEX, "debug");
lua_getfield(m_L, -1, "traceback");
m_error_handler = luaL_ref(m_L, LUA_REGISTRYINDEX);
lua_pop(m_L, 1);
pushErrorHandler();
}
}
int call(int params, int returns) {
int base = lua_gettop(m_L) - params; /* function index */
pushErrorHandler(); /* push traceback function */
lua_insert(m_L, base); /* put it under chunk and args */
int iRet = lua_pcall(m_L, params, returns, base);
if(iRet != 0) {
lua_remove(m_L, base); /* remove traceback function */
TBase* pT = static_cast<TBase*>(this);
pT->OnError(true); // ya obtuve un stack trace, no intentar obtener uno porque no va a existir
return iRet;
}
lua_remove(m_L, base); /* remove traceback function */
return iRet;
}
int cpcall(lua_CFunction function, void* ud) {
//int base = lua_gettop(m_L) - params; /* function index */
//lua_pushcfunction(m_L, CollectTraceback); /* push traceback function */
//lua_insert(m_L, base); /* put it under chunk and args */
int iRet = lua_cpcall(m_L, function, ud);
if(iRet != 0) {
TBase* pT = static_cast<TBase*>(this);
pT->OnError(true); // ya obtuve un stack trace, no intentar obtener uno porque no va a existir
return 0;
}
//lua_remove(m_L, base); /* remove traceback function */
return iRet;
}
int PerformGC(bool full = false) {
if(!full) {
return lua_gc(m_L, LUA_GCCOLLECT, 0);
}
int ret = 0;
int oldCount = 0;
int count = lua_gc(m_L, LUA_GCCOUNT, 0);
while(oldCount != count) {
ret = lua_gc(m_L, LUA_GCCOLLECT, 0);
oldCount = count;
count = lua_gc(m_L, LUA_GCCOUNT, 0);
}
return ret;
}
private:
bool m_owner;
protected:
lua_State* m_L;
int m_error_handler;
};
#endif // !defined(AFX_LUARUNTIME_H__5E316F4C_EE73_4483_B0F0_6619A9D7C653__INCLUDED_)