1 //------------------------------------------------------------------------------
3 https://github.com/vinniefalco/LuaBridge
5 Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
7 License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
16 The above copyright notice and this permission notice shall be included in all
17 copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 //==============================================================================
29 // We use a structure so we can define everything in the header.
33 //----------------------------------------------------------------------------
35 __index metamethod for a namespace or class static members.
38 Retrieving functions and class static methods, stored in the metatable.
39 Reading global and class static data, stored in the __propget table.
40 Reading global and class properties, stored in the __propget table.
42 static int indexMetaMethod (lua_State* L)
45 lua_getmetatable (L, 1); // push metatable of arg1
48 lua_pushvalue (L, 2); // push key arg2
49 lua_rawget (L, -2); // lookup key in metatable
50 if (lua_isnil (L, -1)) // not found
52 lua_pop (L, 1); // discard nil
53 rawgetfield (L, -1, "__propget"); // lookup __propget in metatable
54 lua_pushvalue (L, 2); // push key arg2
55 lua_rawget (L, -2); // lookup key in __propget
56 lua_remove (L, -2); // discard __propget
57 if (lua_iscfunction (L, -1))
59 lua_remove (L, -2); // discard metatable
60 lua_pushvalue (L, 1); // push arg1
61 lua_call (L, 1, 1); // call cfunction
67 assert (lua_isnil (L, -1));
68 lua_pop (L, 1); // discard nil and fall through
73 assert (lua_istable (L, -1) || lua_iscfunction (L, -1));
79 rawgetfield (L, -1, "__parent");
80 if (lua_istable (L, -1))
82 // Remove metatable and repeat the search in __parent.
87 // Discard metatable and return nil.
88 assert (lua_isnil (L, -1));
98 //----------------------------------------------------------------------------
100 __newindex metamethod for a namespace or class static members.
102 The __propset table stores proxy functions for assignment to:
103 Global and class static data.
104 Global and class properties.
106 static int newindexMetaMethod (lua_State* L)
109 lua_getmetatable (L, 1); // push metatable of arg1
112 rawgetfield (L, -1, "__propset"); // lookup __propset in metatable
113 assert (lua_istable (L, -1));
114 lua_pushvalue (L, 2); // push key arg2
115 lua_rawget (L, -2); // lookup key in __propset
116 lua_remove (L, -2); // discard __propset
117 if (lua_iscfunction (L, -1)) // ensure value is a cfunction
119 lua_remove (L, -2); // discard metatable
120 lua_pushvalue (L, 3); // push new value arg3
121 lua_call (L, 1, 0); // call cfunction
127 assert (lua_isnil (L, -1));
131 rawgetfield (L, -1, "__parent");
132 if (lua_istable (L, -1))
134 // Remove metatable and repeat the search in __parent.
139 assert (lua_isnil (L, -1));
141 result = luaL_error (L,"no writable variable '%s'", lua_tostring (L, 2));
148 //----------------------------------------------------------------------------
150 lua_CFunction to report an error writing to a read-only value.
152 The name of the variable is in the first upvalue.
154 static int readOnlyError (lua_State* L)
158 s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only";
160 return luaL_error (L, s.c_str ());
163 //----------------------------------------------------------------------------
165 lua_CFunction to get a variable.
167 This is used for global variables or class static data members.
169 The pointer to the data is in the first upvalue.
172 static int getVariable (lua_State* L)
174 assert (lua_islightuserdata (L, lua_upvalueindex (1)));
175 T const* ptr = static_cast <T const*> (lua_touserdata (L, lua_upvalueindex (1)));
177 Stack <T>::push (L, *ptr);
181 //----------------------------------------------------------------------------
183 lua_CFunction to set a variable.
185 This is used for global variables or class static data members.
187 The pointer to the data is in the first upvalue.
190 static int setVariable (lua_State* L)
192 assert (lua_islightuserdata (L, lua_upvalueindex (1)));
193 T* ptr = static_cast <T*> (lua_touserdata (L, lua_upvalueindex (1)));
195 *ptr = Stack <T>::get (L, 1);
199 //----------------------------------------------------------------------------
201 lua_CFunction to call a function with a return value.
203 This is used for global functions, global properties, class static methods,
204 and class static properties.
206 The function pointer is in the first upvalue.
208 template <class FnPtr,
209 class ReturnType = typename FuncTraits <FnPtr>::ReturnType>
212 typedef typename FuncTraits <FnPtr>::Params Params;
213 static int f (lua_State* L)
215 assert (isfulluserdata (L, lua_upvalueindex (1)));
216 FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
218 ArgList <Params> args (L);
219 Stack <typename FuncTraits <FnPtr>::ReturnType>::push (L, FuncTraits <FnPtr>::call (fnptr, args));
224 //----------------------------------------------------------------------------
226 lua_CFunction to call a function with no return value.
228 This is used for global functions, global properties, class static methods,
229 and class static properties.
231 The function pointer is in the first upvalue.
233 template <class FnPtr>
234 struct Call <FnPtr, void>
236 typedef typename FuncTraits <FnPtr>::Params Params;
237 static int f (lua_State* L)
239 assert (isfulluserdata (L, lua_upvalueindex (1)));
240 FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
242 ArgList <Params> args (L);
243 FuncTraits <FnPtr>::call (fnptr, args);
248 //----------------------------------------------------------------------------
250 lua_CFunction to call a class member function with a return value.
252 The member function pointer is in the first upvalue.
253 The class userdata object is at the top of the Lua stack.
255 template <class MemFnPtr,
256 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
259 typedef typename FuncTraits <MemFnPtr>::ClassType T;
260 typedef typename FuncTraits <MemFnPtr>::Params Params;
262 static int f (lua_State* L)
264 assert (isfulluserdata (L, lua_upvalueindex (1)));
265 T* const t = Userdata::get <T> (L, 1, false);
266 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
268 ArgList <Params, 2> args (L);
269 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
274 template <class MemFnPtr,
275 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
276 struct CallConstMember
278 typedef typename FuncTraits <MemFnPtr>::ClassType T;
279 typedef typename FuncTraits <MemFnPtr>::Params Params;
281 static int f (lua_State* L)
283 assert (isfulluserdata (L, lua_upvalueindex (1)));
284 T const* const t = Userdata::get <T> (L, 1, true);
285 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
287 ArgList <Params, 2> args(L);
288 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
293 //----------------------------------------------------------------------------
295 lua_CFunction to call a class member function with no return value.
297 The member function pointer is in the first upvalue.
298 The class userdata object is at the top of the Lua stack.
300 template <class MemFnPtr>
301 struct CallMember <MemFnPtr, void>
303 typedef typename FuncTraits <MemFnPtr>::ClassType T;
304 typedef typename FuncTraits <MemFnPtr>::Params Params;
306 static int f (lua_State* L)
308 assert (isfulluserdata (L, lua_upvalueindex (1)));
309 T* const t = Userdata::get <T> (L, 1, false);
310 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
312 ArgList <Params, 2> args (L);
313 FuncTraits <MemFnPtr>::call (t, fnptr, args);
318 template <class MemFnPtr>
319 struct CallConstMember <MemFnPtr, void>
321 typedef typename FuncTraits <MemFnPtr>::ClassType T;
322 typedef typename FuncTraits <MemFnPtr>::Params Params;
324 static int f (lua_State* L)
326 assert (isfulluserdata (L, lua_upvalueindex (1)));
327 T const* const t = Userdata::get <T> (L, 1, true);
328 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
330 ArgList <Params, 2> args (L);
331 FuncTraits <MemFnPtr>::call (t, fnptr, args);
336 //--------------------------------------------------------------------------
338 lua_CFunction to call a class member lua_CFunction.
340 The member function pointer is in the first upvalue.
341 The class userdata object is at the top of the Lua stack.
344 struct CallMemberCFunction
346 static int f (lua_State* L)
348 assert (isfulluserdata (L, lua_upvalueindex (1)));
349 typedef int (T::*MFP)(lua_State* L);
350 T* const t = Userdata::get <T> (L, 1, false);
351 MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
353 return (t->*fnptr) (L);
358 struct CallConstMemberCFunction
360 static int f (lua_State* L)
362 assert (isfulluserdata (L, lua_upvalueindex (1)));
363 typedef int (T::*MFP)(lua_State* L);
364 T const* const t = Userdata::get <T> (L, 1, true);
365 MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
367 return (t->*fnptr) (L);
371 //--------------------------------------------------------------------------
375 template <class MemFnPtr, bool isConst>
376 struct CallMemberFunctionHelper
378 static void add (lua_State* L, char const* name, MemFnPtr mf)
380 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
381 lua_pushcclosure (L, &CallConstMember <MemFnPtr>::f, 1);
382 lua_pushvalue (L, -1);
383 rawsetfield (L, -5, name); // const table
384 rawsetfield (L, -3, name); // class table
388 template <class MemFnPtr>
389 struct CallMemberFunctionHelper <MemFnPtr, false>
391 static void add (lua_State* L, char const* name, MemFnPtr mf)
393 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
394 lua_pushcclosure (L, &CallMember <MemFnPtr>::f, 1);
395 rawsetfield (L, -3, name); // class table
399 //--------------------------------------------------------------------------
401 __gc metamethod for a class.
404 static int gcMetaMethod (lua_State* L)
406 Userdata* const ud = Userdata::getExact <C> (L, 1);
411 //--------------------------------------------------------------------------
413 lua_CFunction to get a class data member.
415 The pointer-to-member is in the first upvalue.
416 The class userdata object is at the top of the Lua stack.
418 template <class C, typename T>
419 static int getProperty (lua_State* L)
421 C const* const c = Userdata::get <C> (L, 1, true);
422 T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
423 Stack <T>::push (L, c->**mp);
427 //--------------------------------------------------------------------------
429 lua_CFunction to set a class data member.
431 The pointer-to-member is in the first upvalue.
432 The class userdata object is at the top of the Lua stack.
434 template <class C, typename T>
435 static int setProperty (lua_State* L)
437 C* const c = Userdata::get <C> (L, 1, false);
438 T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
439 c->**mp = Stack <T>::get (L, 2);