1 /***********************************************************************
2 	created:  16/3/2005
3 	author:   Tomas Lindquist Olsen
4 
5 	purpose:  Implementation for LuaScriptModule class
6 *************************************************************************/
7 /***************************************************************************
8  *   Copyright (C) 2004 - 2008 Paul D Turner & The CEGUI Development Team
9  *
10  *   Permission is hereby granted, free of charge, to any person obtaining
11  *   a copy of this software and associated documentation files (the
12  *   "Software"), to deal in the Software without restriction, including
13  *   without limitation the rights to use, copy, modify, merge, publish,
14  *   distribute, sublicense, and/or sell copies of the Software, and to
15  *   permit persons to whom the Software is furnished to do so, subject to
16  *   the following conditions:
17  *
18  *   The above copyright notice and this permission notice shall be
19  *   included in all copies or substantial portions of the Software.
20  *
21  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27  *   OTHER DEALINGS IN THE SOFTWARE.
28  ***************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 #   include "config.h"
31 #endif
32 
33 #include "CEGUI/CEGUI.h"
34 #include "CEGUI/ScriptModules/Lua/ScriptModule.h"
35 #include "CEGUI/ScriptModules/Lua/Functor.h"
36 #include <vector>
37 
38 // include Lua libs and tolua++
39 extern "C" {
40 #include "lua.h"
41 #include "lualib.h"
42 #include "lauxlib.h"
43 }
44 
45 #include "tolua++.h"
46 
47 // prototype for bindings initialisation function
48 int tolua_CEGUI_open(lua_State* tolua_S);
49 
50 
51 // Start of CEGUI namespace section
52 namespace CEGUI
53 {
54 
55 /*************************************************************************
56 	Constructor (creates Lua state)
57 *************************************************************************/
LuaScriptModule(lua_State * state)58 LuaScriptModule::LuaScriptModule(lua_State* state) :
59     d_ownsState(state == 0),
60     d_state(state),
61     d_errFuncIndex(LUA_NOREF),
62     d_activeErrFuncIndex(LUA_NOREF)
63 {
64     // initialise and create a lua_State if one was not provided
65     if (!d_state)
66     {
67         #if CEGUI_LUA_VER >= 51
68             static const luaL_Reg lualibs[] = {
69                 {"", luaopen_base},
70                 {LUA_LOADLIBNAME, luaopen_package},
71                 {LUA_TABLIBNAME, luaopen_table},
72                 {LUA_IOLIBNAME, luaopen_io},
73                 {LUA_OSLIBNAME, luaopen_os},
74                 {LUA_STRLIBNAME, luaopen_string},
75                 {LUA_MATHLIBNAME, luaopen_math},
76             #if defined(DEBUG) || defined (_DEBUG)
77                     {LUA_DBLIBNAME, luaopen_debug},
78             #endif
79                 {0, 0}
80             };
81         #endif /* CEGUI_LUA_VER >= 51 */
82 
83         // create a lua state
84         d_ownsState = true;
85 #if LUA_VERSION_NUM > 501
86         d_state = luaL_newstate();
87 #else
88         d_state = lua_open();
89 #endif
90 
91         // init all standard libraries
92         #if CEGUI_LUA_VER >= 51
93                 const luaL_Reg *lib = lualibs;
94                 for (; lib->func; lib++)
95                 {
96                     lua_pushcfunction(d_state, lib->func);
97                     lua_pushstring(d_state, lib->name);
98                     lua_call(d_state, 1, 0);
99                 }
100         #else /* CEGUI_LUA_VER >= 51 */
101             luaopen_base(d_state);
102             luaopen_io(d_state);
103             luaopen_string(d_state);
104             luaopen_table(d_state);
105             luaopen_math(d_state);
106             #if defined(DEBUG) || defined (_DEBUG)
107                 luaopen_debug(d_state);
108             #endif
109         #endif /* CEGUI_LUA_VER >= 51 */
110     }
111 
112     setModuleIdentifierString();
113 }
114 
115 
116 /*************************************************************************
117 	Destructor
118 *************************************************************************/
~LuaScriptModule()119 LuaScriptModule::~LuaScriptModule()
120 {
121     if (d_state)
122     {
123         unrefErrorFunc();
124 
125         if (d_ownsState)
126             lua_close( d_state );
127     }
128 }
129 
130 
131 /*************************************************************************
132 	Execute script file
133 *************************************************************************/
executeScriptFile(const String & filename,const String & resourceGroup)134 void LuaScriptModule::executeScriptFile(const String& filename,
135     const String& resourceGroup)
136 {
137     int top = lua_gettop(d_state);
138 
139     executeScriptFile_impl(filename, resourceGroup,
140                            initErrorHandlerFunc(),
141                            top);
142 
143     cleanupErrorHandlerFunc();
144 }
145 
146 
147 /*************************************************************************
148 	Execute global script function
149 *************************************************************************/
executeScriptGlobal(const String & function_name)150 int	LuaScriptModule::executeScriptGlobal(const String& function_name)
151 {
152     int top = lua_gettop(d_state);
153     int r = executeScriptGlobal_impl(function_name, initErrorHandlerFunc(), top);
154     cleanupErrorHandlerFunc();
155 
156     return r;
157 }
158 
159 
160 /*************************************************************************
161 	Execute scripted event handler
162 *************************************************************************/
executeScriptedEventHandler(const String & handler_name,const EventArgs & e)163 bool LuaScriptModule::executeScriptedEventHandler(const String& handler_name,
164     const EventArgs& e)
165 {
166     int top = lua_gettop(d_state);
167     bool r = executeScriptedEventHandler_impl(handler_name, e,
168                                               initErrorHandlerFunc(), top);
169     cleanupErrorHandlerFunc();
170 
171     return r;
172 }
173 
174 
175 /*************************************************************************
176 	Execute script code string
177 *************************************************************************/
executeString(const String & str)178 void LuaScriptModule::executeString(const String& str)
179 {
180     int top = lua_gettop(d_state);
181 
182     executeString_impl(str, initErrorHandlerFunc(), top);
183     cleanupErrorHandlerFunc();
184 }
185 
186 
187 /*************************************************************************
188 	Create Lua bindings
189 *************************************************************************/
createBindings(void)190 void LuaScriptModule::createBindings(void)
191 {
192 	CEGUI::Logger::getSingleton().logEvent( "---- Creating Lua bindings ----" );
193 	// init CEGUI module
194 	tolua_CEGUI_open(d_state);
195 }
196 
197 
198 /*************************************************************************
199 	Destroy Lua bindings
200 *************************************************************************/
destroyBindings(void)201 void LuaScriptModule::destroyBindings(void)
202 {
203 	CEGUI::Logger::getSingleton().logEvent( "---- Destroying Lua bindings ----" );
204 	// is this ok ?
205 	lua_pushnil(d_state);
206 	lua_setglobal(d_state,"CEGUI");
207 }
208 
209 
210 /*************************************************************************
211 	Set the ID string for the module
212 *************************************************************************/
setModuleIdentifierString()213 void LuaScriptModule::setModuleIdentifierString()
214 {
215     // set ID string
216     d_identifierString = "CEGUI::LuaScriptModule - Official Lua based scripting module for CEGUI";
217 }
218 
219 
220 /*************************************************************************
221 	Subscribe to a scripted event handler
222 *************************************************************************/
subscribeEvent(EventSet * target,const String & event_name,const String & subscriber_name)223 Event::Connection LuaScriptModule::subscribeEvent(EventSet* target,
224     const String& event_name, const String& subscriber_name)
225 {
226     const String& err_str = getActivePCallErrorHandlerString();
227     const int err_ref     = getActivePCallErrorHandlerReference();
228 
229     Event::Connection con;
230     // do the real subscription
231     if (err_ref == LUA_NOREF)
232     {
233         LuaFunctor functor(d_state, subscriber_name, LUA_NOREF, err_str);
234         con = target->subscribeEvent(event_name, Event::Subscriber(functor));
235         functor.invalidateLuaRefs();
236     }
237     else
238     {
239         LuaFunctor functor(d_state, subscriber_name, LUA_NOREF, err_ref);
240         con = target->subscribeEvent(event_name, Event::Subscriber(functor));
241         functor.invalidateLuaRefs();
242     }
243 
244     // return the event connection
245     return con;
246 }
247 
248 
249 /*************************************************************************
250 	Subscribe to a scripted event handler
251 *************************************************************************/
subscribeEvent(EventSet * target,const String & event_name,Event::Group group,const String & subscriber_name)252 Event::Connection LuaScriptModule::subscribeEvent(EventSet* target,
253     const String& event_name, Event::Group group, const String& subscriber_name)
254 {
255     const String& err_str = getActivePCallErrorHandlerString();
256     const int err_ref     = getActivePCallErrorHandlerReference();
257 
258     Event::Connection con;
259     // do the real subscription
260     if (err_ref == LUA_NOREF)
261     {
262         LuaFunctor functor(d_state, subscriber_name, LUA_NOREF, err_str);
263         con = target->subscribeEvent(event_name, group,
264                                      Event::Subscriber(functor));
265         functor.invalidateLuaRefs();
266     }
267     else
268     {
269         LuaFunctor functor(d_state, subscriber_name, LUA_NOREF, err_ref);
270         con = target->subscribeEvent(event_name, group,
271                                      Event::Subscriber(functor));
272         functor.invalidateLuaRefs();
273     }
274 
275     // return the event connection
276     return con;
277 }
278 
279 //----------------------------------------------------------------------------//
setDefaultPCallErrorHandler(const String & error_handler_function)280 void LuaScriptModule::setDefaultPCallErrorHandler(
281     const String& error_handler_function)
282 {
283     unrefErrorFunc();
284 
285     d_errFuncName = error_handler_function;
286     d_errFuncIndex = LUA_NOREF;
287 }
288 
289 //----------------------------------------------------------------------------//
setDefaultPCallErrorHandler(int function_reference)290 void LuaScriptModule::setDefaultPCallErrorHandler(int function_reference)
291 {
292     unrefErrorFunc();
293 
294     d_errFuncIndex = function_reference;
295     d_errFuncName.clear();
296 }
297 
298 //----------------------------------------------------------------------------//
getActivePCallErrorHandlerString() const299 const String& LuaScriptModule::getActivePCallErrorHandlerString() const
300 {
301     if ((d_activeErrFuncIndex == LUA_NOREF) && d_activeErrFuncName.empty())
302         return d_errFuncName;
303     else
304         return d_activeErrFuncName;
305 }
306 
307 //----------------------------------------------------------------------------//
getActivePCallErrorHandlerReference() const308 int LuaScriptModule::getActivePCallErrorHandlerReference() const
309 {
310     if ((d_activeErrFuncIndex == LUA_NOREF) && d_activeErrFuncName.empty())
311         return d_errFuncIndex;
312     else
313         return d_activeErrFuncIndex;
314 }
315 
316 //----------------------------------------------------------------------------//
initErrorHandlerFunc()317 int LuaScriptModule::initErrorHandlerFunc()
318 {
319     d_activeErrFuncName = d_errFuncName;
320 
321     // should we create a registry reference for named function
322     if ((d_errFuncIndex == LUA_NOREF) && !d_errFuncName.empty())
323     {
324         int top = lua_gettop(d_state);
325 
326         LuaFunctor::pushNamedFunction(d_state, d_errFuncName);
327         // reference function
328         d_errFuncIndex = luaL_ref(d_state, LUA_REGISTRYINDEX);
329 
330         lua_settop(d_state, top);
331     }
332 
333     // init handler via function index in registry
334     return initErrorHandlerFunc(d_errFuncIndex);
335 }
336 
337 //----------------------------------------------------------------------------//
initErrorHandlerFunc(const String func_name)338 int LuaScriptModule::initErrorHandlerFunc(const String func_name)
339 {
340     d_activeErrFuncName = func_name;
341 
342     // string has some text in it?
343     if (!func_name.empty())
344     {
345         LuaFunctor::pushNamedFunction(d_state, func_name);
346         return lua_gettop(d_state);
347     }
348 
349     // use no error handler function.
350     return 0;
351 }
352 
353 //----------------------------------------------------------------------------//
initErrorHandlerFunc(int func)354 int LuaScriptModule::initErrorHandlerFunc(int func)
355 {
356     d_activeErrFuncIndex = func;
357 
358     // check if we have a valid registry index for the error handler function
359     if (func != LUA_NOREF)
360     {
361         lua_rawgeti(d_state, LUA_REGISTRYINDEX, func);
362         return lua_gettop(d_state);
363     }
364 
365     // use no error handler function.
366     return 0;
367 }
368 
369 //----------------------------------------------------------------------------//
cleanupErrorHandlerFunc()370 void LuaScriptModule::cleanupErrorHandlerFunc()
371 {
372     d_activeErrFuncIndex = LUA_NOREF;
373     d_activeErrFuncName.clear();
374 }
375 
376 //----------------------------------------------------------------------------//
unrefErrorFunc()377 void LuaScriptModule::unrefErrorFunc()
378 {
379     if ((d_errFuncIndex != LUA_NOREF) && !d_errFuncName.empty())
380     {
381         luaL_unref(d_state, LUA_REGISTRYINDEX, d_errFuncIndex);
382         d_errFuncIndex = LUA_NOREF;
383     }
384 }
385 
386 //----------------------------------------------------------------------------//
executeScriptFile(const String & filename,const String & resourceGroup,const String & error_handler)387 void LuaScriptModule::executeScriptFile(const String& filename,
388     const String& resourceGroup, const String& error_handler)
389 {
390     int top = lua_gettop(d_state);
391 
392     executeScriptFile_impl(filename, resourceGroup,
393                            initErrorHandlerFunc(error_handler),
394                            top);
395     cleanupErrorHandlerFunc();
396 }
397 
398 //----------------------------------------------------------------------------//
executeScriptFile(const String & filename,const String & resourceGroup,const int error_handler)399 void LuaScriptModule::executeScriptFile(const String& filename,
400     const String& resourceGroup, const int error_handler)
401 {
402     int top = lua_gettop(d_state);
403 
404     executeScriptFile_impl(filename, resourceGroup,
405                            initErrorHandlerFunc(error_handler),
406                            top);
407     cleanupErrorHandlerFunc();
408 }
409 
410 //----------------------------------------------------------------------------//
executeScriptGlobal(const String & function_name,const String & error_handler)411 int LuaScriptModule::executeScriptGlobal(const String& function_name,
412     const String& error_handler)
413 {
414     int top = lua_gettop(d_state);
415     int r = executeScriptGlobal_impl(function_name,
416                                      initErrorHandlerFunc(error_handler),
417                                      top);
418     cleanupErrorHandlerFunc();
419 
420     return r;
421 }
422 
423 //----------------------------------------------------------------------------//
executeScriptGlobal(const String & function_name,const int error_handler)424 int LuaScriptModule::executeScriptGlobal(const String& function_name,
425     const int error_handler)
426 {
427     int top = lua_gettop(d_state);
428     int r = executeScriptGlobal_impl(function_name,
429                                      initErrorHandlerFunc(error_handler),
430                                      top);
431     cleanupErrorHandlerFunc();
432 
433     return r;
434 }
435 
436 //----------------------------------------------------------------------------//
executeScriptedEventHandler(const String & handler_name,const EventArgs & e,const String & error_handler)437 bool LuaScriptModule::executeScriptedEventHandler(const String& handler_name,
438     const EventArgs& e, const String& error_handler)
439 {
440     int top = lua_gettop(d_state);
441 
442     bool r =executeScriptedEventHandler_impl(handler_name, e,
443                                              initErrorHandlerFunc(error_handler),
444                                              top);
445     cleanupErrorHandlerFunc();
446 
447     return r;
448 }
449 
450 //----------------------------------------------------------------------------//
executeScriptedEventHandler(const String & handler_name,const EventArgs & e,const int error_handler)451 bool LuaScriptModule::executeScriptedEventHandler(const String& handler_name,
452     const EventArgs& e, const int error_handler)
453 {
454     int top = lua_gettop(d_state);
455     bool r = executeScriptedEventHandler_impl(handler_name, e,
456                                               initErrorHandlerFunc(error_handler),
457                                               top);
458     cleanupErrorHandlerFunc();
459 
460     return r;
461 }
462 
463 //----------------------------------------------------------------------------//
executeString(const String & str,const String & error_handler)464 void LuaScriptModule::executeString(const String& str,
465     const String& error_handler)
466 {
467     int top = lua_gettop(d_state);
468 
469     executeString_impl(str, initErrorHandlerFunc(error_handler), top);
470     cleanupErrorHandlerFunc();
471 }
472 
473 //----------------------------------------------------------------------------//
executeString(const String & str,const int error_handler)474 void LuaScriptModule::executeString(const String& str, const int error_handler)
475 {
476     int top = lua_gettop(d_state);
477 
478     executeString_impl(str, initErrorHandlerFunc(error_handler), top);
479     cleanupErrorHandlerFunc();
480 }
481 
482 //----------------------------------------------------------------------------//
subscribeEvent(EventSet * target,const String & event_name,const String & subscriber_name,const String & error_handler)483 Event::Connection LuaScriptModule::subscribeEvent(EventSet* target,
484     const String& event_name, const String& subscriber_name,
485     const String& error_handler)
486 {
487     // do the real subscription
488     LuaFunctor functor(d_state, subscriber_name, LUA_NOREF, error_handler);
489     Event::Connection con =
490         target->subscribeEvent(event_name, Event::Subscriber(functor));
491 
492     // make sure we don't release the references we just made when 'functor' is
493     // destroyed as it goes out of scope.
494     functor.index = LUA_NOREF;
495     functor.d_errFuncIndex = LUA_NOREF;
496 
497     // return the event connection
498     return con;
499 }
500 
501 //----------------------------------------------------------------------------//
subscribeEvent(EventSet * target,const String & event_name,const String & subscriber_name,const int error_handler)502 Event::Connection LuaScriptModule::subscribeEvent(EventSet* target,
503     const String& event_name, const String& subscriber_name,
504     const int error_handler)
505 {
506     // do the real subscription
507     LuaFunctor functor(d_state, subscriber_name, LUA_NOREF, error_handler);
508     Event::Connection con =
509         target->subscribeEvent(event_name, Event::Subscriber(functor));
510 
511     // make sure we don't release the references we just made when 'functor' is
512     // destroyed as it goes out of scope.
513     functor.index = LUA_NOREF;
514     functor.d_errFuncIndex = LUA_NOREF;
515 
516     // return the event connection
517     return con;
518 }
519 
520 
521 //----------------------------------------------------------------------------//
subscribeEvent(EventSet * target,const String & event_name,Event::Group group,const String & subscriber_name,const String & error_handler)522 Event::Connection LuaScriptModule::subscribeEvent(EventSet* target,
523     const String& event_name, Event::Group group, const String& subscriber_name,
524     const String& error_handler)
525 {
526     // do the real subscription
527     LuaFunctor functor(d_state, subscriber_name, LUA_NOREF, error_handler);
528     Event::Connection con =
529         target->subscribeEvent(event_name, group, Event::Subscriber(functor));
530 
531     // make sure we don't release the references we just made when 'functor' is
532     // destroyed as it goes out of scope.
533     functor.index = LUA_NOREF;
534     functor.d_errFuncIndex = LUA_NOREF;
535 
536     // return the event connection
537     return con;
538 }
539 
540 //----------------------------------------------------------------------------//
subscribeEvent(EventSet * target,const String & event_name,Event::Group group,const String & subscriber_name,const int error_handler)541 Event::Connection LuaScriptModule::subscribeEvent(EventSet* target,
542     const String& event_name, Event::Group group, const String& subscriber_name,
543     const int error_handler)
544 {
545     // do the real subscription
546     LuaFunctor functor(d_state, subscriber_name, LUA_NOREF, error_handler);
547     Event::Connection con =
548         target->subscribeEvent(event_name, group, Event::Subscriber(functor));
549 
550     // make sure we don't release the references we just made when 'functor' is
551     // destroyed as it goes out of scope.
552     functor.index = LUA_NOREF;
553     functor.d_errFuncIndex = LUA_NOREF;
554 
555     // return the event connection
556     return con;
557 }
558 
559 //----------------------------------------------------------------------------//
executeScriptFile_impl(const String & filename,const String & resourceGroup,const int err_idx,const int top)560 void LuaScriptModule::executeScriptFile_impl(const String& filename,
561     const String& resourceGroup, const int err_idx, const int top)
562 {
563     // load file
564     RawDataContainer raw;
565     System::getSingleton().getResourceProvider()->loadRawDataContainer(filename,
566         raw, resourceGroup.empty() ? d_defaultResourceGroup : resourceGroup);
567 
568     // load code into lua
569     int loaderr = luaL_loadbuffer(d_state,
570                                   reinterpret_cast<char*>(raw.getDataPtr()),
571                                   raw.getSize(), filename.c_str());
572 
573     System::getSingleton().getResourceProvider()->unloadRawDataContainer( raw );
574 
575     if (loaderr)
576     {
577         String errMsg = lua_tostring(d_state,-1);
578         lua_settop(d_state,top);
579         CEGUI_THROW(ScriptException("Unable to execute Lua script file: '" +
580             filename + "'\n\n" + errMsg + "\n"));
581     }
582 
583     // call it
584     if (lua_pcall(d_state, 0, 0, err_idx))
585     {
586         String errMsg = lua_tostring(d_state,-1);
587         lua_settop(d_state,top);
588         CEGUI_THROW(ScriptException("Unable to execute Lua script file: '" +
589             filename + "'\n\n" + errMsg + "\n"));
590     }
591 
592     lua_settop(d_state,top); // just in case :P
593 }
594 
595 //----------------------------------------------------------------------------//
executeScriptGlobal_impl(const String & function_name,const int err_idx,const int top)596 int LuaScriptModule::executeScriptGlobal_impl(const String& function_name,
597     const int err_idx, const int top)
598 {
599     // get the function from lua
600     lua_getglobal(d_state, function_name.c_str());
601 
602     // is it a function
603     if (!lua_isfunction(d_state,-1))
604     {
605         lua_settop(d_state,top);
606         CEGUI_THROW(ScriptException("Unable to get Lua global: '" +
607             function_name + "' as name not represent a global Lua function" ));
608     }
609 
610     // call it
611     int error = lua_pcall(d_state, 0, 1, err_idx);
612 
613     // handle errors
614     if (error)
615     {
616         String errMsg = lua_tostring(d_state,-1);
617         lua_settop(d_state,top);
618         CEGUI_THROW(ScriptException("Unable to evaluate Lua global: '" +
619             function_name + "\n\n" + errMsg + "\n"));
620     }
621 
622     // get return value
623     if (!lua_isnumber(d_state,-1))
624     {
625         // log that return value is invalid. return -1 and move on.
626         lua_settop(d_state,top);
627         CEGUI_THROW(ScriptException("Unable to get Lua global : '" + function_name +
628                         "' return value as it's not a number"));
629         return -1;
630     }
631 
632     int ret = static_cast<int>(lua_tonumber(d_state,-1));
633     lua_settop(d_state,top);
634 
635     // return it
636     return ret;
637 }
638 
639 //----------------------------------------------------------------------------//
executeScriptedEventHandler_impl(const String & handler_name,const EventArgs & e,const int err_idx,const int top)640 bool LuaScriptModule::executeScriptedEventHandler_impl(
641     const String& handler_name, const EventArgs& e, const int err_idx,
642     const int top)
643 {
644     LuaFunctor::pushNamedFunction(d_state, handler_name);
645 
646     // push EventArgs as the first parameter
647     tolua_pushusertype(d_state, (void*)&e, "const CEGUI::EventArgs");
648 
649     // call it
650     int error = lua_pcall(d_state, 1, 1, err_idx);
651 
652     // handle errors
653     if (error)
654     {
655         String errStr(lua_tostring(d_state,-1));
656         lua_settop(d_state,top);
657 
658         CEGUI_THROW(ScriptException("Unable to evaluate the Lua event "
659             "handler: '" + handler_name + "'\n\n" + errStr + "\n"));
660     }
661 
662     // retrieve result
663     bool ret = lua_isboolean(d_state, -1) ? lua_toboolean(d_state, -1 ) : true;
664     lua_settop(d_state,top);
665 
666     return ret;
667 }
668 
669 //----------------------------------------------------------------------------//
executeString_impl(const String & str,const int err_idx,const int top)670 void LuaScriptModule::executeString_impl(const String& str, const int err_idx,
671     const int top)
672 {
673     // load code into lua and call it
674     int error = luaL_loadbuffer(d_state, str.c_str(), str.length(), str.c_str()) ||
675                 lua_pcall(d_state, 0, 0, err_idx);
676 
677     // handle errors
678     if (error)
679     {
680         String errMsg = lua_tostring(d_state,-1);
681         lua_settop(d_state,top);
682         CEGUI_THROW(ScriptException("Unable to execute Lua script string: '" +
683             str + "'\n\n" + errMsg + "\n"));
684     }
685 
686     lua_settop(d_state,top);
687 }
688 
689 //----------------------------------------------------------------------------//
create(lua_State * state)690 LuaScriptModule& LuaScriptModule::create(lua_State* state)
691 {
692     return *new LuaScriptModule(state);
693 }
694 
695 //----------------------------------------------------------------------------//
destroy(LuaScriptModule & mod)696 void LuaScriptModule::destroy(LuaScriptModule& mod)
697 {
698     delete &mod;
699 }
700 
701 //----------------------------------------------------------------------------//
702 
703 } // namespace CEGUI
704