Fix issue in Rocket.lua script.
[Cafu-Engine.git] / Libs / UniScriptState.hpp
blob123276e2b74bab274fbfa8cc5f8c26ab1c305670
1 /*
2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
5 */
7 #ifndef CAFU_UNI_SCRIPT_STATE_HPP_INCLUDED
8 #define CAFU_UNI_SCRIPT_STATE_HPP_INCLUDED
10 #include "Templates/Array.hpp"
11 #include "Templates/Pointer.hpp"
12 #include "TypeSys.hpp"
14 extern "C"
16 #include <lua.h>
17 #include <lualib.h>
18 #include <lauxlib.h>
21 #include <cstdarg>
22 #include <string>
25 namespace cf
27 /// This class checks if the Lua stack has the same size at the start and the end of a function.
28 class StackCheckerT
30 public:
32 StackCheckerT(lua_State* LuaState, int Change=0)
33 : m_LuaState(LuaState),
34 m_StartTop(lua_gettop(m_LuaState) + Change)
38 ~StackCheckerT()
40 assert(m_StartTop == lua_gettop(m_LuaState));
44 private:
46 lua_State* m_LuaState; ///< The Lua state we're checking the stack for.
47 const int m_StartTop; ///< The initial size of the stack.
51 /// This class implements and encapsulates the strategy with which we bind C++ objects to Lua.
52 ///
53 /// It is separate from class UniScriptStateT, because it can also be used "outside" of script states,
54 /// e.g. in the CFunctions of the bound C++ classes. Moreover, it would be possible to derive from
55 /// this class in order to implement alternative binding strategies, and to pass a concrete instance
56 /// to the UniScriptStateT constructor in order to "configure" it for a particular strategy.
57 ///
58 /// Key idea: we only pass by value!
59 /// - object is copied
60 /// - Lua "owns" it and thus determines its lifetime
61 /// - per default, always create new userdata
62 /// - simple and clear if the object has no identity: push an xyz-vector twice --> two different userdata
63 /// - if the object is a smart pointer, and has identity (entities or windows):
64 /// it would work, too, with one detail issue: per-object extensions added by Lua code (e.g. attributes or callbacks) would not be consistent:
65 /// one userdata representing the identity would have them, but not another
66 /// ==> no problem, treat smart pointers as special case
67 ///
68 /// Each type(name) can only be used with *one* kind of binding:
69 /// MyClassT A();
70 /// IntrusivePtrT<MyClassT> B(new MyClassT());
71 ///
72 /// Push(A);
73 /// Push(B); // This is not possible!
74 /// This is because we can only have one __gc function per type: for this typename, would we call
75 /// Destruct<T>(...) with T == MyClassT or with T == IntrusivePtrT<MyClassT> ?
76 /// and because the type's CFunction callbacks (for example, BaseEntityT::GetOrigin()) would similary not know with which T to call GetCheckedObjectParam<T>().
77 ///
78 /// Literature:
79 /// - Programming in Lua, 2nd edition, Roberto Ierusalimschy
80 /// - Game Programming Gems 6, chapter 4.2, "Binding C/C++ objects to Lua", W. Celes et al.
81 /// - 2008-04-01: http://thread.gmane.org/gmane.comp.lang.lua.general/46787
82 class ScriptBinderT
84 public:
86 /// The constructor.
87 ScriptBinderT(lua_State* LuaState);
89 /// This method registers all C++ classes known to the TIM in the related Lua state.
90 ///
91 /// Subsequently created Lua instances of these classes will use the related information
92 /// so that script code can call the C++-implemented methods, e.g. "obj:myCppFunc()".
93 /// The method also takes inheritance into account: Lua instances of derived classes can
94 /// access the attributes and call the methods of their base classes.
95 void Init(const cf::TypeSys::TypeInfoManT& TIM);
97 /// Pushes the given C++ object onto the stack.
98 /// The object must support the GetType() method (should we add a "const char* TypeName" parameter instead?).
99 template<class T> bool Push(T Object);
101 /// Checks if the value at the given stack index is a Lua object of type T::TypeInfo,
102 /// or a subclass derived from it, and returns a reference to the related userdata.
103 /// (If T is really an IntrusivePtrT<U>, the method checks for type U::TypeInfo,
104 /// or a subclass derived from it.)
105 template<class T> T& GetCheckedObjectParam(int StackIndex);
107 /// Returns if the object with the given identity is currently bound to the Lua state,
108 /// i.e. whether for the C++ object there is an alter ego in Lua.
109 bool IsBound(void* Identity);
111 /// Breaks the connection between a C++ object and its alter ego in Lua.
112 /// If the object with the given identity still has an alter ego in the Lua state,
113 /// calling this method essentially removes all C++ parts from it: the metatable is
114 /// reset to nil, and the userdata's destructor is called (Lua will collect it later).
115 /// After this method, any attempt to access the C++-implemented methods in Lua
116 /// yields a (safe and well-defined) error message.
117 void Disconnect(void* Identity);
120 private:
122 /// Use traits for obtaining information from objects of any given type T.
123 /// If we have an instance of T, call GetType() instead, which returns the proper type
124 /// even if T is a base class pointer.
125 /// See http://erdani.com/publications/traits.html for a nice intro to traits.
126 template<class T> class TraitsT
128 public:
130 static T* GetIdentity(T& Object) { return &Object; }
131 static const cf::TypeSys::TypeInfoT& GetTypeInfo() { return T::TypeInfo; }
132 static const cf::TypeSys::TypeInfoT& GetTypeInfo(const T& Object) { return *Object.GetType(); }
133 static bool IsRefCounted() { return false; }
136 /// Specialization of TraitsT for IntrusivePtrTs to T.
137 template<class T> class TraitsT< IntrusivePtrT<T> >
139 public:
141 static T* GetIdentity(IntrusivePtrT<T> Object) { return Object.get(); }
142 static const cf::TypeSys::TypeInfoT& GetTypeInfo() { return T::TypeInfo; }
143 static const cf::TypeSys::TypeInfoT& GetTypeInfo(IntrusivePtrT<T> Object) { return *Object->GetType(); }
144 static bool IsRefCounted() { return true; }
147 friend class UniScriptStateT;
149 /// Implements the one-time initialization of the Lua state for this binder.
150 /// Called by the UniScriptStateT constructor.
151 void InitState();
153 /// If the object at the given stack index is an IntrusivePtrT, this method anchors it in a separate table
154 /// so that it cannot be garbage collected in Lua while it has siblings in C++.
156 /// The method first checks if the object at the given stack index is an IntrusivePtrT.
157 /// Its reference count is expected to be at least 2 if the IntrusivePtrT was just passed in from C++ code
158 /// and a copy of it was bound to Lua, or at least 1 if Lua has the only instance (that however might soon
159 /// be returned to C++ code, where it can be copied and kept, thereby increasing the reference count).
160 /// In any case, if the object is an IntrusivePtrT, it is added to the REGISTRY.__has_ref_in_cpp set.
162 /// This prevents the object, when it becomes (otherwise) unused in Lua, from being garbage collected.
163 /// It would normally not be a problem at all for an IntrusivePtrT object being collected, and it would be
164 /// perfectly possible to push another copy of an IntrusivePtrT to the same C++ object later.
166 /// The only downside with garbage collecting IntrusivePtrT's that are still referenced in C++ is that any
167 /// custom Lua data that is attached to it, such as event callback functions, gets lost.
168 /// See http://thread.gmane.org/gmane.comp.lang.lua.general/92550 for details.
170 /// Addressing this problem is in fact the sole reason for this method.
171 /// See CheckCppRefs() for the complementary method that un-anchors the objects again.
172 void Anchor(int StackIndex);
174 /// This method un-anchors IntrusivePtrT objects that no longer have any siblings in C++.
176 /// For such IntrusivePtrT's, the Lua instance is the only remaining reference to the C++ object.
177 /// Removing such objects from the REGISTRY.__has_ref_in_cpp set ensures that they can normally be
178 /// garbage collected as soon as they become unused in Lua as well.
180 /// The user must call this method periodically (typically every n-th game frame).
182 /// In summary, the key idea of the whole anchoring process is:
183 /// 1) When an object is newly pushed, anchor it.
184 /// 2) Every now and then, run our own "pseudo garbage collection":
185 /// a) When the object becomes unused in C++, un-anchor it.
186 /// b) If the object is passed back to C++ again, re-anchor it.
188 /// See Anchor() for the complementary method that (re-)anchors IntrusivePtrT objects.
189 void CheckCppRefs();
191 /// If i is a negative stack index (relative to the top), returns the related absolute index.
192 int abs_index(int i) const
194 return (i > 0 || i <= LUA_REGISTRYINDEX) ? i : lua_gettop(m_LuaState) + i + 1;
197 /// An extra object method for objects of type IntrusivePtrT<X>.
198 template<class T> static int GetRefCount(lua_State* LuaState);
200 /// The callback for the __gc metamethod.
201 template<class T> static int Destruct(lua_State* LuaState);
203 lua_State* m_LuaState; ///< The Lua state that this binder is used with.
207 /// This class represents the state of a script:
208 /// the underlying Lua state, pending coroutines, metatables for C++ class hierarchies, etc.
210 /// Its main features are:
211 /// - easy calling of Lua chunks, functions and object methods from C++ (Run() and Call()),
212 /// - easy to use support for coroutines/threads: Lua code can call "thread()" and "wait()",
213 /// - easy creation of Lua instances for C++ objects and binding of C++-implemented methods.
214 class UniScriptStateT
216 public:
218 /// The constructor.
219 UniScriptStateT();
221 /// The destructor.
222 ~UniScriptStateT();
224 /// Loads the given string as a Lua chunk, then runs it.
225 /// (This acts very much like the stand-alone Lua interpreter.)
226 bool DoString(const char* s, const char* Signature = "", ...);
228 /// Loads the given file as a Lua chunk, then runs it.
229 bool DoFile(const char* FileName, const char* Signature = "", ...);
231 /// Calls the global script function with the given name.
233 /// @param FuncName The name of the global script function to be called.
234 /// @param Signature Describes the arguments to and results from the Lua function. See below for more details.
235 /// @param ... The arguments to the Lua function and the variables that receive its results as described by the Signature parameter.
237 /// The Signature parameter is a string of individual letters, where each letter represents a variable and its type.
238 /// The letters 'b' for bool, 'i' for int, 'f' for float, 'd' for double and 's' for const char* (string) can be used.
239 /// A '>' separates the arguments from the results, and is optional if the function returns no results.
240 /// For the results, additionally to the other letters, 'S' can be used for (address of) std::string.
242 /// @returns whether the function call was successful.
243 /// Note that when a signature was provided that expects one or more return values and the called script code yields
244 /// (calls coroutine.yield()), the returned values are undefined and thus the call is considered a failure and false is returned.
245 /// Nonetheless, the related Lua thread is added to the list of pending coroutines for later resumption.
246 bool Call(const char* FuncName, const char* Signature="", ...);
248 /// Calls a method with the given name of the given object.
250 /// @param Object The object whose script method is to be called.
251 /// @param MethodName The name of the method to be called.
252 /// @param Signature Describes the arguments to and results from the Lua method.
253 /// @param ... The arguments to the Lua method and the variables that receive its results as described by the Signature parameter.
255 /// For more details about the parameters and return value, see Call().
257 /// Example:
258 /// If the variable Obj is bound to Object, then CallMethod(Object, "OnTrigger", "f", 1.0);
259 /// calls the script method Obj:OnTrigger(value) where value is a number with value 1.0.
260 template<class T> bool CallMethod(T Object, const std::string& MethodName, const char* Signature="", ...);
262 /// Like CallMethod() above, but the arguments and results are passed via vl rather than "...",
263 /// and if any extra arguments have been pushed on the stack, their number must be given.
264 /// Note that the "extra arguments" are a work-around that was not necessary if we could use
265 /// variadic templates for the implementation of CallMethod().
266 template<class T> bool CallMethod_Impl(T Object, const std::string& MethodName, int NumExtraArgs, const char* Signature, va_list vl);
268 /// Runs the pending coroutines.
269 void RunPendingCoroutines(float FrameTime);
271 /// Returns the Lua state that implements this script state.
272 lua_State* GetLuaState() { return m_LuaState; }
275 private:
277 class CoroutineT
279 public:
281 CoroutineT();
283 unsigned int ID; ///< The unique ID of this coroutine, used to anchor it in a table in the Lua registry. Automatically set in the constructor, but not declared const so that CoroutineT objects can be kept in an ArrayT<>.
284 lua_State* State; ///< The state and stack of this coroutine.
285 unsigned int NumParams; ///< Number of parameters on the stack of State for the next call to lua_resume(), i.e. the parameters for the initial function call or the return values for the pending yield().
286 float WaitTimeLeft; ///< Wait time left until the next call to lua_resume().
289 private:
291 static unsigned int InstCount; ///< Count of created instances, used for creating unique coroutine IDs.
294 UniScriptStateT(const UniScriptStateT&); ///< Use of the Copy Constructor is not allowed.
295 void operator = (const UniScriptStateT&); ///< Use of the Assignment Operator is not allowed.
297 /// This method calls a Lua function in the context of the Lua state.
298 bool StartNewCoroutine(int NumExtraArgs, const char* Signature, va_list vl, const std::string& DbgName);
300 /// A global Lua function that registers the given Lua function as a new thread.
301 static int RegisterThread(lua_State* LuaState);
303 /// A helper function for checking if a called Lua function is documented.
304 static void CheckCallbackDoc(const cf::TypeSys::TypeInfoT* TI, const std::string& MethodName, int NumExtraArgs, const char* Signature);
306 lua_State* m_LuaState; ///< The Lua instance. This is what "really" represents the script.
307 ArrayT<CoroutineT> m_PendingCoroutines; ///< The list of active, pending coroutines.
308 unsigned int m_CheckCppRefsCount; ///< Call Binder.CheckCppRefs() only every n-th frame.
313 template<class T> int cf::ScriptBinderT::GetRefCount(lua_State* LuaState)
315 // Cannot use Binder.GetCheckedObjectParam() here, because it would cause infinite
316 // recursion (via the call to Anchor()).
317 lua_getfield(LuaState, -1, "__userdata_cf");
319 // Note that T is an IntrusivePtrT<X>.
320 T* UserData=(T*)lua_touserdata(LuaState, -1);
322 assert(UserData);
323 lua_pushinteger(LuaState, UserData ? (*UserData)->GetRefCount() : 0);
324 return 1;
328 template<class T> int cf::ScriptBinderT::Destruct(lua_State* LuaState)
330 T* UserData=(T*)lua_touserdata(LuaState, 1);
332 if (UserData)
334 // Explicitly call the destructor for the placed object.
335 UserData->~T();
338 return 0;
342 template<class T> inline bool cf::ScriptBinderT::Push(T Object)
344 const StackCheckerT StackChecker(m_LuaState, 1);
346 // Put the REGISTRY["__identity_to_object"] table onto the stack.
347 lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "__identity_to_object");
349 // Put __identity_to_object[Identity] onto the stack.
350 // This should be our table that represents the object.
351 lua_pushlightuserdata(m_LuaState, TraitsT<T>::GetIdentity(Object)); // Need the raw "identity" pointer here.
352 lua_rawget(m_LuaState, -2);
354 // If the object was not found in __identity_to_object, create it anew.
355 if (lua_isnil(m_LuaState, -1))
357 // Remove the nil.
358 lua_pop(m_LuaState, 1);
360 // Stack indices of the table and userdata that we process here.
361 const int USERDATA_INDEX=lua_gettop(m_LuaState) + 2;
362 const int TABLE_INDEX =lua_gettop(m_LuaState) + 1;
364 // Create a new object table OT, which is pushed on the stack and thus at stack index TABLE_INDEX.
365 lua_newtable(m_LuaState);
367 // Create a new user datum UD, which is pushed on the stack and thus at stack index USERDATA_INDEX.
368 new (lua_newuserdata(m_LuaState, sizeof(T))) T(Object);
370 // OT["__userdata_cf"] = UD
371 lua_pushvalue(m_LuaState, USERDATA_INDEX); // Duplicate the userdata on top of the stack.
372 lua_setfield(m_LuaState, TABLE_INDEX, "__userdata_cf");
374 // Get the table with name (key) TraitsT<T>::GetTypeInfo(Object).ClassName from the registry,
375 // and check if its __gc metamethod is already set.
376 // Note that starting with Lua 5.2, the __gc field must be set *before* the table is set as metatable (below),
377 // or else the finalizer will not be called even if it is set later (see ยง2.5.1 in the Lua Reference Manual).
378 luaL_getmetatable(m_LuaState, TraitsT<T>::GetTypeInfo(Object).ClassName);
379 assert(lua_istable(m_LuaState, -1));
380 lua_getfield(m_LuaState, -1, "__gc");
381 if (lua_isnil(m_LuaState, -1))
383 lua_pushcfunction(m_LuaState, Destruct<T>);
384 lua_setfield(m_LuaState, -3, "__gc");
386 lua_pop(m_LuaState, 2);
388 // Get the table with name TraitsT<T>::GetTypeInfo(Object).ClassName from the registry,
389 // and set it as metatable of the newly created table.
390 // This is the crucial step that establishes the main functionality of our new table.
391 luaL_getmetatable(m_LuaState, TraitsT<T>::GetTypeInfo(Object).ClassName);
392 assert(lua_istable(m_LuaState, -1));
393 lua_setmetatable(m_LuaState, TABLE_INDEX);
395 // Get the table with name (key) TraitsT<T>::GetTypeInfo(Object).ClassName from the registry,
396 // and set it as metatable of the newly created userdata item.
397 // This is important for userdata type safety (see PiL2, chapter 28.2) and to have automatic garbage collection work
398 // (contrary to the text in the "Game Programming Gems 6" book, chapter 4.2, a __gc method in the metatable
399 // is only called for full userdata, see my email to the Lua mailing list on 2008-Apr-01 for more details).
400 luaL_getmetatable(m_LuaState, TraitsT<T>::GetTypeInfo(Object).ClassName);
401 assert(lua_istable(m_LuaState, -1));
402 lua_setmetatable(m_LuaState, USERDATA_INDEX);
404 // Get the table for the root of TraitsT<T>::GetTypeInfo(Object) from the registry,
405 // get its __index table, and check if its GetRefCount method is already set.
406 if (TraitsT<T>::IsRefCounted())
408 const cf::TypeSys::TypeInfoT* TI = &TraitsT<T>::GetTypeInfo(Object);
410 while (TI->Base)
411 TI = TI->Base;
413 luaL_getmetatable(m_LuaState, TI->ClassName);
414 lua_getfield(m_LuaState, -1, "__index");
415 lua_getfield(m_LuaState, -1, "GetRefCount");
416 if (lua_isnil(m_LuaState, -1))
418 lua_pushcfunction(m_LuaState, GetRefCount<T>);
419 lua_setfield(m_LuaState, -3, "GetRefCount");
421 lua_pop(m_LuaState, 3);
424 // Remove UD from the stack, so that now the new table OT is on top of the stack.
425 lua_pop(m_LuaState, 1);
427 // Record the table: __identity_to_object[Identity] = OT
428 lua_pushlightuserdata(m_LuaState, TraitsT<T>::GetIdentity(Object)); // Need the raw "identity" pointer here.
429 lua_pushvalue(m_LuaState, TABLE_INDEX); // Duplicate the table on top of the stack.
430 lua_rawset(m_LuaState, -4);
432 // Anchor the object (table OT).
433 // Note that this is not necessary if the object was found in __identity_to_object above,
434 // because then, clearly a copy in C++ and a copy in Lua existed beforehand, so that
435 // consequently the object must also be anchored.
436 Anchor(TABLE_INDEX);
439 // Remove the __identity_to_object table.
440 lua_remove(m_LuaState, -2);
442 // The requested table/userdata is now at the top of the stack.
443 return true;
447 template<class T> inline T& cf::ScriptBinderT::GetCheckedObjectParam(int StackIndex)
449 // Don't bother with stack checking, because here it can only work in the case of success.
450 // If there is an error, not only do we not clean up the stack, but the error message itself is
451 // a problem as well: See http://thread.gmane.org/gmane.comp.lang.lua.general/103390 for details.
452 // const StackCheckerT StackChecker(m_LuaState);
454 StackIndex = abs_index(StackIndex);
456 // First make sure that the table that represents the object itself is at StackIndex.
457 luaL_argcheck(m_LuaState, lua_istable(m_LuaState, StackIndex), StackIndex, "Expected a table that represents an object." /*of type TypeInfo.ClassName*/);
459 // Put the contents of the "__userdata_cf" field on top of the stack (other values may be between it and the table at position StackIndex).
460 lua_getfield(m_LuaState, StackIndex, "__userdata_cf");
462 #if 1
463 // This approach takes inheritance properly into account by "manually traversing up the inheritance hierarchy".
464 // See the "Game Programming Gems 6" book, page 353 for the inspiration for this code.
466 // Put the metatable of the desired type on top of the stack.
467 luaL_getmetatable(m_LuaState, TraitsT<T>::GetTypeInfo().ClassName);
469 // Put the metatable for the given userdata on top of the stack (it may belong to a derived class).
470 if (!lua_getmetatable(m_LuaState, -2)) lua_pushnil(m_LuaState); // Don't have it push nothing in case of failure.
472 while (lua_istable(m_LuaState, -1))
474 if (lua_rawequal(m_LuaState, -1, -2))
476 T* UserData=(T*)lua_touserdata(m_LuaState, -3);
478 if (UserData==NULL)
479 luaL_error(m_LuaState, "NULL userdata in object table.");
481 // Pop the two matching metatables and the userdata.
482 lua_pop(m_LuaState, 3);
484 // We pass the object back to C++, fully expecting that it will keep a copy
485 // and, if it is an IntrusivePtrT, increase its reference count.
486 Anchor(StackIndex);
488 return *UserData;
491 // Replace the metatable MT on top of the stack with the metatable of MT.__index.
492 lua_getfield(m_LuaState, -1, "__index");
493 if (!lua_getmetatable(m_LuaState, -1)) lua_pushnil(m_LuaState); // Don't have it push nothing in case of failure.
494 lua_remove(m_LuaState, -2);
495 lua_remove(m_LuaState, -2);
498 // luaL_typerror(m_LuaState, StackIndex, TraitsT<T>::GetTypeInfo().ClassName);
499 luaL_argerror(m_LuaState, StackIndex, lua_pushfstring(m_LuaState, "%s expected, got %s", TraitsT<T>::GetTypeInfo().ClassName, luaL_typename(m_LuaState, StackIndex)));
501 static T* Invalid = NULL;
502 return *Invalid;
503 #else
504 // This approach is too simplistic, it doesn't work when inheritance is used.
505 T* UserData=(T*)luaL_checkudata(m_LuaState, -1, TraitsT<T>::GetTypeInfo().ClassName);
507 if (UserData==NULL)
508 luaL_error(m_LuaState, "NULL userdata in object table.");
510 // Pop the userdata from the stack again. Not necessary though as it doesn't hurt there.
511 // lua_pop(m_LuaState, 1);
512 return *UserData;
513 #endif
517 template<class T> inline bool cf::UniScriptStateT::CallMethod(T Object, const std::string& MethodName, const char* Signature, ...)
519 va_list vl;
521 va_start(vl, Signature);
522 const bool Result=CallMethod_Impl(Object, MethodName, 0, Signature, vl);
523 va_end(vl);
525 return Result;
529 template<class T> inline bool cf::UniScriptStateT::CallMethod_Impl(T Object, const std::string& MethodName, int NumExtraArgs, const char* Signature, va_list vl)
531 const StackCheckerT StackChecker(m_LuaState, -NumExtraArgs);
532 cf::ScriptBinderT Binder(m_LuaState);
534 #ifdef DEBUG
535 CheckCallbackDoc(Object->GetType(), MethodName, NumExtraArgs, Signature);
536 #endif
538 Binder.Push(Object);
540 // Put the desired method (directly from the object's table or
541 // from its metatables __index table) onto the stack of LuaState.
542 lua_getfield(m_LuaState, -1, MethodName.c_str());
544 if (!lua_isfunction(m_LuaState, -1))
546 // If we get here, this usually means that the value at -1 is just nil, i.e. the
547 // function that we would like to call was just not defined in the Lua script.
548 // Pop whatever is not a function, the object table, and any extra arguments.
549 lua_pop(m_LuaState, 2 + NumExtraArgs);
550 return false;
553 // Rearrange the stack from "method, Object, extra arguments" to "extra arguments, Object, method",
554 // so that the function call sees the Object as its first argument (the "self" or "this" value for
555 // the object-oriented method call), followed by any extra arguments.
556 lua_insert(m_LuaState, -2 - NumExtraArgs); // Move the method below the Object and the extra args.
557 lua_insert(m_LuaState, -1 - NumExtraArgs); // Move the Object below the extra args.
559 // The stack is now prepared as required by the StartNewCoroutine() method.
560 return StartNewCoroutine(1 + NumExtraArgs, Signature, vl, std::string("method ") + MethodName + "()");
563 #endif