diff options
Diffstat (limited to 'src/FbTk')
-rw-r--r-- | src/FbTk/Luamm.cc | 101 | ||||
-rw-r--r-- | src/FbTk/Luamm.hh | 109 |
2 files changed, 108 insertions, 102 deletions
diff --git a/src/FbTk/Luamm.cc b/src/FbTk/Luamm.cc index d17096f..ff3669f 100644 --- a/src/FbTk/Luamm.cc +++ b/src/FbTk/Luamm.cc | |||
@@ -221,51 +221,56 @@ namespace lua { | |||
221 | } | 221 | } |
222 | 222 | ||
223 | state::state() | 223 | state::state() |
224 | : cobj(luaL_newstate()) | ||
224 | { | 225 | { |
225 | if(lua_State *l = luaL_newstate()) | 226 | if(cobj == NULL) { |
226 | cobj.reset(l, &lua_close); | ||
227 | else { | ||
228 | // docs say this can happen only in case of a memory allocation error | 227 | // docs say this can happen only in case of a memory allocation error |
229 | throw std::bad_alloc(); | 228 | throw std::bad_alloc(); |
230 | } | 229 | } |
231 | 230 | ||
232 | // set our panic function | 231 | try { |
233 | lua_atpanic(cobj.get(), panic_throw); | 232 | // set our panic function |
234 | 233 | lua_atpanic(cobj, panic_throw); | |
235 | checkstack(2); | 234 | |
236 | 235 | checkstack(2); | |
237 | // store a pointer to ourselves | 236 | |
238 | pushlightuserdata(this); | 237 | // store a pointer to ourselves |
239 | rawsetfield(REGISTRYINDEX, this_cpp_object); | 238 | pushlightuserdata(this); |
240 | 239 | rawsetfield(REGISTRYINDEX, this_cpp_object); | |
241 | // a metatable for C++ exceptions travelling through lua code | 240 | |
242 | newmetatable(cpp_exception_metatable); | 241 | // a metatable for C++ exceptions travelling through lua code |
243 | lua_pushcfunction(cobj.get(), &exception_to_string); | 242 | newmetatable(cpp_exception_metatable); |
244 | rawsetfield(-2, "__tostring"); | 243 | lua_pushcfunction(cobj, &exception_to_string); |
245 | pushboolean(false); | 244 | rawsetfield(-2, "__tostring"); |
246 | rawsetfield(-2, "__metatable"); | 245 | pushboolean(false); |
247 | pushdestructor<std::exception_ptr>(); | 246 | rawsetfield(-2, "__metatable"); |
248 | rawsetfield(-2, "__gc"); | 247 | pushdestructor<std::exception_ptr>(); |
249 | pop(); | 248 | rawsetfield(-2, "__gc"); |
250 | 249 | pop(); | |
251 | // a metatable for C++ functions callable from lua code | 250 | |
252 | newmetatable(cpp_function_metatable); | 251 | // a metatable for C++ functions callable from lua code |
253 | pushboolean(false); | 252 | newmetatable(cpp_function_metatable); |
254 | rawsetfield(-2, "__metatable"); | 253 | pushboolean(false); |
255 | pushdestructor<FbTk::Slot<int, state *> >(); | 254 | rawsetfield(-2, "__metatable"); |
256 | rawsetfield(-2, "__gc"); | 255 | pushdestructor<FbTk::Slot<int, state *> >(); |
257 | pop(); | 256 | rawsetfield(-2, "__gc"); |
258 | 257 | pop(); | |
259 | // while they're travelling through C++ code, lua exceptions will reside here | 258 | |
260 | newtable(); | 259 | // while they're travelling through C++ code, lua exceptions will reside here |
261 | rawsetfield(REGISTRYINDEX, lua_exception_namespace); | 260 | newtable(); |
262 | 261 | rawsetfield(REGISTRYINDEX, lua_exception_namespace); | |
263 | luaL_openlibs(cobj.get()); | 262 | |
263 | luaL_openlibs(cobj); | ||
264 | } | ||
265 | catch(...) { | ||
266 | lua_close(cobj); | ||
267 | throw; | ||
268 | } | ||
264 | } | 269 | } |
265 | 270 | ||
266 | void state::call(int nargs, int nresults, int errfunc) | 271 | void state::call(int nargs, int nresults, int errfunc) |
267 | { | 272 | { |
268 | int r = lua_pcall(cobj.get(), nargs, nresults, errfunc); | 273 | int r = lua_pcall(cobj, nargs, nresults, errfunc); |
269 | if(r == 0) | 274 | if(r == 0) |
270 | return; | 275 | return; |
271 | 276 | ||
@@ -301,7 +306,7 @@ namespace lua { | |||
301 | 306 | ||
302 | void state::checkstack(int extra) throw(std::bad_alloc) | 307 | void state::checkstack(int extra) throw(std::bad_alloc) |
303 | { | 308 | { |
304 | if(not lua_checkstack(cobj.get(), extra)) | 309 | if(not lua_checkstack(cobj, extra)) |
305 | throw std::bad_alloc(); | 310 | throw std::bad_alloc(); |
306 | } | 311 | } |
307 | 312 | ||
@@ -309,7 +314,7 @@ namespace lua { | |||
309 | { | 314 | { |
310 | assert(n>=0); | 315 | assert(n>=0); |
311 | checkstack(1); | 316 | checkstack(1); |
312 | lua_pushcfunction(cobj.get(), safe_concat_trampoline); | 317 | lua_pushcfunction(cobj, safe_concat_trampoline); |
313 | insert(-n-1); | 318 | insert(-n-1); |
314 | call(n, 1, 0); | 319 | call(n, 1, 0); |
315 | } | 320 | } |
@@ -326,7 +331,7 @@ namespace lua { | |||
326 | int state::gc(int what, int data) | 331 | int state::gc(int what, int data) |
327 | { | 332 | { |
328 | checkstack(3); | 333 | checkstack(3); |
329 | lua_pushcfunction(cobj.get(), safe_gc_trampoline); | 334 | lua_pushcfunction(cobj, safe_gc_trampoline); |
330 | pushinteger(what); | 335 | pushinteger(what); |
331 | pushinteger(data); | 336 | pushinteger(data); |
332 | call(2, 1, 0); | 337 | call(2, 1, 0); |
@@ -349,7 +354,7 @@ namespace lua { | |||
349 | checkstack(2); | 354 | checkstack(2); |
350 | pushvalue(index); | 355 | pushvalue(index); |
351 | insert(-2); | 356 | insert(-2); |
352 | lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_gettable, 1>)); | 357 | lua_pushcfunction(cobj, (&safe_misc_trampoline<&lua_gettable, 1>)); |
353 | insert(-3); | 358 | insert(-3); |
354 | call(2, 1, 0); | 359 | call(2, 1, 0); |
355 | } | 360 | } |
@@ -362,7 +367,7 @@ namespace lua { | |||
362 | void state::loadfile(const char *filename) | 367 | void state::loadfile(const char *filename) |
363 | throw(lua::syntax_error, lua::file_error, std::bad_alloc) | 368 | throw(lua::syntax_error, lua::file_error, std::bad_alloc) |
364 | { | 369 | { |
365 | switch(luaL_loadfile(cobj.get(), filename)) { | 370 | switch(luaL_loadfile(cobj, filename)) { |
366 | case 0: | 371 | case 0: |
367 | return; | 372 | return; |
368 | case LUA_ERRSYNTAX: | 373 | case LUA_ERRSYNTAX: |
@@ -378,7 +383,7 @@ namespace lua { | |||
378 | 383 | ||
379 | void state::loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc) | 384 | void state::loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc) |
380 | { | 385 | { |
381 | switch(luaL_loadstring(cobj.get(), s)) { | 386 | switch(luaL_loadstring(cobj, s)) { |
382 | case 0: | 387 | case 0: |
383 | return; | 388 | return; |
384 | case LUA_ERRSYNTAX: | 389 | case LUA_ERRSYNTAX: |
@@ -395,7 +400,7 @@ namespace lua { | |||
395 | checkstack(2); | 400 | checkstack(2); |
396 | pushvalue(index); | 401 | pushvalue(index); |
397 | insert(-2); | 402 | insert(-2); |
398 | lua_pushcfunction(cobj.get(), &safe_next_trampoline); | 403 | lua_pushcfunction(cobj, &safe_next_trampoline); |
399 | insert(-3); | 404 | insert(-3); |
400 | 405 | ||
401 | call(2, MULTRET, 0); | 406 | call(2, MULTRET, 0); |
@@ -416,10 +421,10 @@ namespace lua { | |||
416 | } | 421 | } |
417 | 422 | ||
418 | void state::rawgetfield(int index, const char *k) throw(std::bad_alloc) | 423 | void state::rawgetfield(int index, const char *k) throw(std::bad_alloc) |
419 | { lua::rawgetfield(cobj.get(), index, k); } | 424 | { lua::rawgetfield(cobj, index, k); } |
420 | 425 | ||
421 | void state::rawsetfield(int index, const char *k) throw(std::bad_alloc) | 426 | void state::rawsetfield(int index, const char *k) throw(std::bad_alloc) |
422 | { lua::rawsetfield(cobj.get(), index, k); } | 427 | { lua::rawsetfield(cobj, index, k); } |
423 | 428 | ||
424 | bool state::safe_compare(lua_CFunction trampoline, int index1, int index2) | 429 | bool state::safe_compare(lua_CFunction trampoline, int index1, int index2) |
425 | { | 430 | { |
@@ -432,7 +437,7 @@ namespace lua { | |||
432 | index2 = absindex(index2); | 437 | index2 = absindex(index2); |
433 | 438 | ||
434 | checkstack(3); | 439 | checkstack(3); |
435 | lua_pushcfunction(cobj.get(), trampoline); | 440 | lua_pushcfunction(cobj, trampoline); |
436 | pushvalue(index1); | 441 | pushvalue(index1); |
437 | pushvalue(index2); | 442 | pushvalue(index2); |
438 | call(2, 1, 0); | 443 | call(2, 1, 0); |
@@ -456,7 +461,7 @@ namespace lua { | |||
456 | checkstack(2); | 461 | checkstack(2); |
457 | pushvalue(index); | 462 | pushvalue(index); |
458 | insert(-3); | 463 | insert(-3); |
459 | lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_settable, 0>)); | 464 | lua_pushcfunction(cobj, (&safe_misc_trampoline<&lua_settable, 0>)); |
460 | insert(-4); | 465 | insert(-4); |
461 | call(3, 0, 0); | 466 | call(3, 0, 0); |
462 | } | 467 | } |
@@ -464,7 +469,7 @@ namespace lua { | |||
464 | std::string state::tostring(int index) throw(lua::not_string_error) | 469 | std::string state::tostring(int index) throw(lua::not_string_error) |
465 | { | 470 | { |
466 | size_t len; | 471 | size_t len; |
467 | const char *str = lua_tolstring(cobj.get(), index, &len); | 472 | const char *str = lua_tolstring(cobj, index, &len); |
468 | if(not str) | 473 | if(not str) |
469 | throw not_string_error(); | 474 | throw not_string_error(); |
470 | return std::string(str, len); | 475 | return std::string(str, len); |
diff --git a/src/FbTk/Luamm.hh b/src/FbTk/Luamm.hh index e173be9..6b26a17 100644 --- a/src/FbTk/Luamm.hh +++ b/src/FbTk/Luamm.hh | |||
@@ -130,29 +130,30 @@ namespace lua { | |||
130 | 130 | ||
131 | // a fancy wrapper around lua_State | 131 | // a fancy wrapper around lua_State |
132 | class state { | 132 | class state { |
133 | std::shared_ptr<lua_State> cobj; | 133 | lua_State *cobj; |
134 | 134 | ||
135 | // destructor for C++ objects stored as lua userdata | 135 | // destructor for C++ objects stored as lua userdata |
136 | template<typename T> | 136 | template<typename T> |
137 | static int destroy_cpp_object(lua_State *l) | 137 | static int destroy_cpp_object(lua_State *l) |
138 | { | 138 | { |
139 | T *ptr = static_cast<T *>(lua_touserdata(l, -1)); | 139 | T *ptr = static_cast<T *>(lua_touserdata(l, -1)); |
140 | assert(ptr); | 140 | assert(ptr); |
141 | try { | 141 | try { |
142 | // throwing exceptions in destructors is a bad idea | 142 | // throwing exceptions in destructors is a bad idea |
143 | // but we catch (and ignore) them, just in case | 143 | // but we catch (and ignore) them, just in case |
144 | ptr->~T(); | 144 | ptr->~T(); |
145 | } | ||
146 | catch(...) { | ||
147 | } | ||
148 | return 0; | ||
149 | } | 145 | } |
146 | catch(...) { | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | 150 | ||
151 | bool safe_compare(lua_CFunction trampoline, int index1, int index2); | 151 | bool safe_compare(lua_CFunction trampoline, int index1, int index2); |
152 | void do_pushclosure(int n); | 152 | void do_pushclosure(int n); |
153 | 153 | ||
154 | public: | 154 | public: |
155 | state(); | 155 | state(); |
156 | ~state() { lua_close(cobj); } | ||
156 | 157 | ||
157 | /* | 158 | /* |
158 | * Lua functions come in three flavours | 159 | * Lua functions come in three flavours |
@@ -179,68 +180,68 @@ namespace lua { | |||
179 | 180 | ||
180 | // type a, never throw | 181 | // type a, never throw |
181 | int absindex(int index) throw() { return index<0 && -index<=gettop() ? gettop()+1+index : index; } | 182 | int absindex(int index) throw() { return index<0 && -index<=gettop() ? gettop()+1+index : index; } |
182 | bool getmetatable(int index) throw() { return lua_getmetatable(cobj.get(), index); } | 183 | bool getmetatable(int index) throw() { return lua_getmetatable(cobj, index); } |
183 | int gettop() throw() { return lua_gettop(cobj.get()); } | 184 | int gettop() throw() { return lua_gettop(cobj); } |
184 | void insert(int index) throw() { lua_insert(cobj.get(), index); } | 185 | void insert(int index) throw() { lua_insert(cobj, index); } |
185 | bool isboolean(int index) throw() { return lua_isboolean(cobj.get(), index); } | 186 | bool isboolean(int index) throw() { return lua_isboolean(cobj, index); } |
186 | bool isfunction(int index) throw() { return lua_isfunction(cobj.get(), index); } | 187 | bool isfunction(int index) throw() { return lua_isfunction(cobj, index); } |
187 | bool islightuserdata(int index) throw() { return lua_islightuserdata(cobj.get(), index); } | 188 | bool islightuserdata(int index) throw() { return lua_islightuserdata(cobj, index); } |
188 | bool isnil(int index) throw() { return lua_isnil(cobj.get(), index); } | 189 | bool isnil(int index) throw() { return lua_isnil(cobj, index); } |
189 | bool isnone(int index) throw() { return lua_isnone(cobj.get(), index); } | 190 | bool isnone(int index) throw() { return lua_isnone(cobj, index); } |
190 | bool isnumber(int index) throw() { return lua_isnumber(cobj.get(), index); } | 191 | bool isnumber(int index) throw() { return lua_isnumber(cobj, index); } |
191 | bool isstring(int index) throw() { return lua_isstring(cobj.get(), index); } | 192 | bool isstring(int index) throw() { return lua_isstring(cobj, index); } |
192 | void pop(int n = 1) throw() { lua_pop(cobj.get(), n); } | 193 | void pop(int n = 1) throw() { lua_pop(cobj, n); } |
193 | void pushboolean(bool b) throw() { lua_pushboolean(cobj.get(), b); } | 194 | void pushboolean(bool b) throw() { lua_pushboolean(cobj, b); } |
194 | void pushinteger(integer n) throw() { lua_pushinteger(cobj.get(), n); } | 195 | void pushinteger(integer n) throw() { lua_pushinteger(cobj, n); } |
195 | void pushlightuserdata(void *p) throw() { lua_pushlightuserdata(cobj.get(), p); } | 196 | void pushlightuserdata(void *p) throw() { lua_pushlightuserdata(cobj, p); } |
196 | void pushnil() throw() { lua_pushnil(cobj.get()); } | 197 | void pushnil() throw() { lua_pushnil(cobj); } |
197 | void pushnumber(number n) throw() { lua_pushnumber(cobj.get(), n); } | 198 | void pushnumber(number n) throw() { lua_pushnumber(cobj, n); } |
198 | void pushvalue(int index) throw() { lua_pushvalue(cobj.get(), index); } | 199 | void pushvalue(int index) throw() { lua_pushvalue(cobj, index); } |
199 | void rawget(int index) throw() { lua_rawget(cobj.get(), index); } | 200 | void rawget(int index) throw() { lua_rawget(cobj, index); } |
200 | void rawgeti(int index, int n) throw() { lua_rawgeti(cobj.get(), index, n); } | 201 | void rawgeti(int index, int n) throw() { lua_rawgeti(cobj, index, n); } |
201 | bool rawequal(int index1, int index2) throw() { return lua_rawequal(cobj.get(), index1, index2); } | 202 | bool rawequal(int index1, int index2) throw() { return lua_rawequal(cobj, index1, index2); } |
202 | void replace(int index) throw() { lua_replace(cobj.get(), index); } | 203 | void replace(int index) throw() { lua_replace(cobj, index); } |
203 | // lua_setmetatable returns int, but docs don't specify it's meaning :/ | 204 | // lua_setmetatable returns int, but docs don't specify it's meaning :/ |
204 | int setmetatable(int index) throw() { return lua_setmetatable(cobj.get(), index); } | 205 | int setmetatable(int index) throw() { return lua_setmetatable(cobj, index); } |
205 | void settop(int index) throw() { return lua_settop(cobj.get(), index); } | 206 | void settop(int index) throw() { return lua_settop(cobj, index); } |
206 | bool toboolean(int index) throw() { return lua_toboolean(cobj.get(), index); } | 207 | bool toboolean(int index) throw() { return lua_toboolean(cobj, index); } |
207 | integer tointeger(int index) throw() { return lua_tointeger(cobj.get(), index); } | 208 | integer tointeger(int index) throw() { return lua_tointeger(cobj, index); } |
208 | number tonumber(int index) throw() { return lua_tonumber(cobj.get(), index); } | 209 | number tonumber(int index) throw() { return lua_tonumber(cobj, index); } |
209 | void* touserdata(int index) throw() { return lua_touserdata(cobj.get(), index); } | 210 | void* touserdata(int index) throw() { return lua_touserdata(cobj, index); } |
210 | Type type(int index) throw() { return static_cast<Type>(lua_type(cobj.get(), index)); } | 211 | Type type(int index) throw() { return static_cast<Type>(lua_type(cobj, index)); } |
211 | // typename is a reserved word :/ | 212 | // typename is a reserved word :/ |
212 | const char* type_name(Type tp) throw() { return lua_typename(cobj.get(), tp); } | 213 | const char* type_name(Type tp) throw() { return lua_typename(cobj, tp); } |
213 | void unref(int t, int ref) throw() { return luaL_unref(cobj.get(), t, ref); } | 214 | void unref(int t, int ref) throw() { return luaL_unref(cobj, t, ref); } |
214 | 215 | ||
215 | // type b, throw only on memory allocation errors | 216 | // type b, throw only on memory allocation errors |
216 | // checkstack correctly throws bad_alloc, because lua_checkstack kindly informs us of | 217 | // checkstack correctly throws bad_alloc, because lua_checkstack kindly informs us of |
217 | // that sitution | 218 | // that sitution |
218 | void checkstack(int extra) throw(std::bad_alloc); | 219 | void checkstack(int extra) throw(std::bad_alloc); |
219 | const char* gsub(const char *s, const char *p, const char *r) { return luaL_gsub(cobj.get(), s, p, r); } | 220 | const char* gsub(const char *s, const char *p, const char *r) { return luaL_gsub(cobj, s, p, r); } |
220 | bool newmetatable(const char *tname) { return luaL_newmetatable(cobj.get(), tname); } | 221 | bool newmetatable(const char *tname) { return luaL_newmetatable(cobj, tname); } |
221 | void newtable() { lua_newtable(cobj.get()); } | 222 | void newtable() { lua_newtable(cobj); } |
222 | void *newuserdata(size_t size) { return lua_newuserdata(cobj.get(), size); } | 223 | void *newuserdata(size_t size) { return lua_newuserdata(cobj, size); } |
223 | // Functor can be anything that FbTk::Slot can handle, everything else remains | 224 | // Functor can be anything that FbTk::Slot can handle, everything else remains |
224 | // identical | 225 | // identical |
225 | template<typename Functor> | 226 | template<typename Functor> |
226 | void pushclosure(const Functor &fn, int n); | 227 | void pushclosure(const Functor &fn, int n); |
227 | template<typename Functor> | 228 | template<typename Functor> |
228 | void pushfunction(const Functor &fn) { pushclosure(fn, 0); } | 229 | void pushfunction(const Functor &fn) { pushclosure(fn, 0); } |
229 | void pushstring(const char *s) { lua_pushstring(cobj.get(), s); } | 230 | void pushstring(const char *s) { lua_pushstring(cobj, s); } |
230 | void pushstring(const char *s, size_t len) { lua_pushlstring(cobj.get(), s, len); } | 231 | void pushstring(const char *s, size_t len) { lua_pushlstring(cobj, s, len); } |
231 | void pushstring(const std::string &s) { lua_pushlstring(cobj.get(), s.c_str(), s.size()); } | 232 | void pushstring(const std::string &s) { lua_pushlstring(cobj, s.c_str(), s.size()); } |
232 | void rawgetfield(int index, const char *k) throw(std::bad_alloc); | 233 | void rawgetfield(int index, const char *k) throw(std::bad_alloc); |
233 | void rawset(int index) { lua_rawset(cobj.get(), index); } | 234 | void rawset(int index) { lua_rawset(cobj, index); } |
234 | void rawsetfield(int index, const char *k) throw(std::bad_alloc); | 235 | void rawsetfield(int index, const char *k) throw(std::bad_alloc); |
235 | int ref(int t) { return luaL_ref(cobj.get(), t); } | 236 | int ref(int t) { return luaL_ref(cobj, t); } |
236 | // len recieves length, if not null. Returned value may contain '\0' | 237 | // len recieves length, if not null. Returned value may contain '\0' |
237 | const char* tocstring(int index, size_t *len = NULL) { return lua_tolstring(cobj.get(), index, len); } | 238 | const char* tocstring(int index, size_t *len = NULL) { return lua_tolstring(cobj, index, len); } |
238 | // Don't use pushclosure() to create a __gc function. The problem is that lua calls them | 239 | // Don't use pushclosure() to create a __gc function. The problem is that lua calls them |
239 | // in an unspecified order, and we may end up destroying the object holding the | 240 | // in an unspecified order, and we may end up destroying the object holding the |
240 | // std::function before we get a chance to call it. This pushes a function that simply | 241 | // std::function before we get a chance to call it. This pushes a function that simply |
241 | // calls ~T when the time comes. Only set it as __gc on userdata of type T. | 242 | // calls ~T when the time comes. Only set it as __gc on userdata of type T. |
242 | template<typename T> | 243 | template<typename T> |
243 | void pushdestructor() { lua_pushcfunction(cobj.get(), &destroy_cpp_object<T>); } | 244 | void pushdestructor() { lua_pushcfunction(cobj, &destroy_cpp_object<T>); } |
244 | 245 | ||
245 | // type c, throw everything but the kitchen sink | 246 | // type c, throw everything but the kitchen sink |
246 | // call() is a protected mode call, we don't allow unprotected calls | 247 | // call() is a protected mode call, we don't allow unprotected calls |