libmoldeo (Moldeo 1.0 Core)  1.0
libmoldeo is the group of objects and functions that executes the basic operations of Moldeo 1.0 Platform.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
moLuna.h
Go to the documentation of this file.
1 /*******************************************************************************
2 
3  moLuna.h
4 
5  ****************************************************************************
6  * *
7  * This source is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This code is distributed in the hope that it will be useful, but *
13  * WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15  * General Public License for more details. *
16  * *
17  * A copy of the GNU General Public License is available on the World *
18  * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
19  * obtain it by writing to the Free Software Foundation, *
20  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  * *
22  ****************************************************************************
23 
24  Copyright(C) 2006 Fabricio Costa
25 
26  Authors:
27  Fabricio Costa
28  Andrés Colubri
29 
30  Description:
31  Implementa un método para agregar clases de moldeo a la máquina virtual de LUA,
32  de manera tal que puedan ser creadas y accedidas desde los scripts. Para mas
33  información al respecto:
34  http://lua-users.org/wiki/SimpleCppBinding
35  http://lua-users.org/wiki/SimplerCppBinding
36  http://lua-users.org/wiki/CppBindingWithLunar
37  Cada link describe un método diferente, el que se utiliza aquí es el segundo.
38 
39  Fabricio Costa > versión 2011 implementada en base a:
40  http://lua-users.org/wiki/LunaFourCode
41  http://lua-users.org/wiki/LunaFour
42 
43 *******************************************************************************/
44 
45 #ifndef __MO_LUNA_H__
46 #define __MO_LUNA_H__
47 
48 #include "moTypes.h"
49 
50 #undef check
51 
53 #include <string>
54 #include <vector>
55 #include <list>
56 
57 extern "C"
58 {
59  #include "lua.h"
60  #include "lauxlib.h"
61  #include "lualib.h"
62 }
63 
68 template <typename T> class moLuna {
69  typedef struct { T *pT; } userdataType;
70 public:
71 
73  enum { NUMBER, STRING };
74 
76  struct PropertyType {
77  const char *name;
78  int (T::*getter) (lua_State *);
79  int (T::*setter) (lua_State *);
80  };
81 
83  struct FunctionType {
84  const char *name;
85  int (T::*function) (lua_State *);
86  };
87 
88 
90  //typedef int (T::*mfp)(lua_State *L);
91  //typedef struct { const char *name; mfp mfunc; } RegType;
92 
93 
95 
105  /*
106  static T *check(lua_State * L, int narg) {
107  // Check to see whether we are a table
108  if (lua_istable(L,narg+1))
109  {
110  lua_gettablevalue(L,narg+1,0);
111  userdataType *ud =
112  static_cast <userdataType * >(luaL_checkudata(L, -1, T::className));
113  if (!ud)
114  luaL_typerror(L, narg+1, T::className);
115  lua_pop(L,1);
116  return ud->pT; // pointer to T object
117  }
118  else
119  {
120  luaL_typerror(L, narg+1, T::className);
121  }
122  }
123 */
136 
148  /*
149  static T *lightcheck(lua_State * L, int narg) {
150  // Check to see whether we are a table
151  if (lua_istable(L,narg+1))
152  {
153  lua_gettablevalue(L,narg+1,0); ///doesn't work
154  userdataType *ud =
155  static_cast <userdataType * >(luaL_testudata(L, -1, T::className));
156  if (!ud)
157  return NULL; // lightcheck returns NULL if not found.
158  lua_pop(L,1);
159  return ud->pT; // pointer to T object
160  }
161  else
162  {
163  return NULL;
164  }
165  }
166 */
167 
173  /*
174  static void Register(lua_State *L) {
175  lua_newtable(L);
176  int methods = lua_gettop(L);
177 
178  luaL_newmetatable(L, T::className);
179  int metatable = lua_gettop(L);
180 
181  // store method table in globals so that
182  // scripts can add functions written in Lua.
183  lua_pushstring(L, T::className);
184  lua_pushvalue(L, methods);
185  lua_settable(L, LUA_GLOBALSINDEX);
186 
187  lua_pushliteral(L, "__metatable");
188  lua_pushvalue(L, methods);
189  lua_settable(L, metatable); // hide metatable from Lua getmetatable()
190 
191  lua_pushliteral(L, "__index");
192  lua_pushvalue(L, methods);
193  lua_settable(L, metatable);
194 
195  lua_pushliteral(L, "__tostring");
196  lua_pushcfunction(L, tostring_T);
197  lua_settable(L, metatable);
198 
199  lua_pushliteral(L, "__gc");
200  lua_pushcfunction(L, gc_T);
201  lua_settable(L, metatable);
202 
203  lua_newtable(L); // mt for method table
204  int mt = lua_gettop(L);
205  lua_pushliteral(L, "__call");
206  lua_pushcfunction(L, new_T);
207  lua_pushliteral(L, "new");
208  lua_pushvalue(L, -2); // dup new_T function
209  lua_settable(L, methods); // add new_T to method table
210  lua_settable(L, mt); // mt.__call = new_T
211  lua_setmetatable(L, methods);
212 
213  // fill method table with methods from class T
214  for (RegType *l = T::methods; l->name; l++) {
215  // edited by Snaily: shouldn't it be const RegType *l ... ?
216  lua_pushstring(L, l->name);
217  lua_pushlightuserdata(L, (void*)l);
218  lua_pushcclosure(L, thunk, 1);
219  lua_settable(L, methods);
220  }
221 
222  lua_pop(L, 2); // drop metatable and method table
223  }
224 */
225 
227 
236  // REGISTER CLASS AS A GLOBAL TABLE
237  static void Register(lua_State * L, const char *namespac = "") {
238 
239  if (strcmp(namespac, "") != 0) {
240  lua_getglobal(L, namespac);
241  lua_pushcfunction(L, &moLuna < T >::constructor);
242  lua_setfield(L, -2, T::className);
243  lua_pop(L, 1);
244  } else {
245  lua_pushcfunction(L, &moLuna < T >::constructor);
246  lua_setglobal(L, T::className);
247  }
248 
249  luaL_newmetatable(L, T::className);
250  int metatable = lua_gettop(L);
251 
252  lua_pushstring(L, "__gc");
253  lua_pushcfunction(L, &moLuna < T >::gc_obj);
254  lua_settable(L, metatable);
255 
256  lua_pushstring(L, "__index");
257  lua_pushcfunction(L, &moLuna < T >::property_getter);
258  lua_settable(L, metatable);
259 
260  lua_pushstring(L, "__setindex");
261  lua_pushcfunction(L, &moLuna < T >::property_setter);
262  lua_settable(L, metatable);
263 
264  }
265 
267 
274  static int constructor(lua_State * L) {
275 
276  lua_newtable(L);
277 
278  int newtable = lua_gettop(L);
279 
280  lua_pushnumber(L, 0);
281 
282  T **a = (T **) lua_newuserdata(L, sizeof(T *));
283  //correction
284  //T *obj = new T(L, true);
285  T *obj = new T(L);
286  *a = obj;
287 
288  int userdata = lua_gettop(L);
289 
290  luaL_getmetatable(L, T::className);
291 
292  lua_setmetatable(L, userdata);
293 
294  lua_settable(L, newtable);
295 
296  luaL_getmetatable(L, T::className);
297  lua_setmetatable(L, newtable);
298 
299  luaL_getmetatable(L, T::className);
300 
301  for (int i = 0; T::Properties[i].name; i++) {
302  lua_pushstring(L, T::Properties[i].name);
303  lua_pushnumber(L, i);
304  lua_settable(L, -3);
305  }
306 
307  lua_pop(L, 1);
308 
309  for (int i = 0; T::Functions[i].name; i++) {
310  lua_pushstring(L, T::Functions[i].name);
311  lua_pushnumber(L, i);
312  lua_pushcclosure(L, &moLuna < T >::function_dispatch, 1);
313  lua_settable(L, newtable);
314  }
315 
316  return 1;
317  }
318 
328  static T *createNew(lua_State * L) {
329 
330  lua_newtable(L);
331 
332  int newtable = lua_gettop(L);
333 
334  lua_pushnumber(L, 0);
335 
336  T **a = (T **) lua_newuserdata(L, sizeof(T *));
337  T *obj = new T(L, false);
338  obj->isExisting = false;
339  *a = obj;
340 
341  int userdata = lua_gettop(L);
342 
343  luaL_getmetatable(L, T::className);
344 
345  lua_setmetatable(L, userdata);
346 
347  lua_settable(L, newtable);
348 
349  luaL_getmetatable(L, T::className);
350  lua_setmetatable(L, newtable);
351 
352  luaL_getmetatable(L, T::className);
353 
354  for (int i = 0; T::Properties[i].name; i++) {
355  // ADD NAME KEY
356  lua_pushstring(L, T::Properties[i].name);
357  lua_pushnumber(L, i);
358  lua_settable(L, -3);
359  }
360 
361  lua_pop(L, 1);
362 
363  for (int i = 0; T::Functions[i].name; i++) {
364  lua_pushstring(L, T::Functions[i].name);
365  lua_pushnumber(L, i);
366  lua_pushcclosure(L, &moLuna < T >::function_dispatch, 1);
367  lua_settable(L, newtable);
368  }
369 
370  return obj;
371  }
372 
384  static T *createFromExisting(lua_State * L, T * existingobj) {
385 
386  lua_newtable(L);
387 
388  int newtable = lua_gettop(L);
389 
390  lua_pushnumber(L, 0);
391 
392  T **a = (T **) lua_newuserdata(L, sizeof(T *));
393  T *obj = existingobj;
394  obj->isExisting = true;
395  *a = obj;
396 
397  int userdata = lua_gettop(L);
398 
399 
400  luaL_getmetatable(L, T::className);
401 
402  lua_setmetatable(L, userdata);
403 
404  lua_settable(L, newtable);
405 
406  luaL_getmetatable(L, T::className);
407  lua_setmetatable(L, newtable);
408 
409  luaL_getmetatable(L, T::className);
410 
411  for (int i = 0; T::Properties[i].name; i++) {
412  lua_pushstring(L, T::Properties[i].name);
413  lua_pushnumber(L, i);
414  lua_settable(L, -3);
415  }
416 
417  lua_pop(L, 1);
418 
419  for (int i = 0; T::Functions[i].name; i++) {
420  lua_pushstring(L, T::Functions[i].name);
421  lua_pushnumber(L, i);
422  lua_pushcclosure(L, &moLuna < T >::function_dispatch, 1);
423  lua_settable(L, newtable);
424  }
425 
426  return obj;
427  }
428 
435  static int property_getter(lua_State * L) {
436 
437  lua_pushvalue(L, 2);
438 
439  lua_getmetatable(L, 1);
440 
441  lua_pushvalue(L, 2);
442  lua_rawget(L, -2);
443 
444  if (lua_isnumber(L, -1)) {
445 
446  int _index = lua_tonumber(L, -1);
447 
448  lua_pushnumber(L, 0);
449  lua_rawget(L, 1);
450 
451  T **obj =
452  static_cast < T ** >(lua_touserdata(L, -1));
453 
454  lua_pushvalue(L, 3);
455 
456  //const PropertyType *_properties = (*obj)->T::Properties;
457 
458  int result = ((*obj)->*(T::Properties[_index].getter)) (L);
459 
460  return result;
461 
462  }
463  // PUSH NIL
464  lua_pushnil(L);
465 
466  return 1;
467 
468  }
469 
476  static int property_setter(lua_State * L) {
477 
478  lua_getmetatable(L, 1);
479 
480  lua_pushvalue(L, 2);
481  lua_rawget(L, -2);
482 
483  if (lua_isnil(L, -1)) {
484 
485  lua_pop(L, 2);
486 
487  lua_rawset(L, 1);
488 
489  return 0;
490  } else {
491 
492  int _index = lua_tonumber(L, -1);
493 
494  lua_pushnumber(L, 0);
495  lua_rawget(L, 1);
496 
497  T **obj =
498  static_cast < T ** >(lua_touserdata(L, -1));
499 
500  lua_pushvalue(L, 3);
501 
502  //const PropertyType *_properties = (*obj)->T::Properties;
503 
504  return ((*obj)->*(T::Properties[_index].setter)) (L);
505 
506  }
507 
508  }
509 
516  static int function_dispatch(lua_State * L) {
517 
518  int i = (int) lua_tonumber(L, lua_upvalueindex(1));
519 
520  lua_pushnumber(L, 0);
521  lua_rawget(L, 1);
522 
523  T **obj = static_cast < T ** >(lua_touserdata(L, -1));
524 
525  lua_pop(L, 1);
526 
527  return ((*obj)->*(T::Functions[i].function)) (L);
528  }
529 
536  static int gc_obj(lua_State * L) {
537 
538  T **obj =
539  static_cast < T ** >(luaL_checkudata(L, -1, T::className));
540 
541  if (!(*obj)->isExisting && !(*obj)->isPrecious)
542  {
543  cout << "Cleaning up a " << T::className << "." << endl;
544  delete(*obj);
545  }
546 
547  return 0;
548  }
549 
550 
551 private:
552 
553 /*
554  moLuna(); // hide default constructor
555 
556 
557  // member function dispatcher
558  static int thunk(lua_State *L) {
559  // stack has userdata, followed by method args
560  T *obj = check(L, 1); // get 'self', or if you prefer, 'this'
561  lua_remove(L, 1); // remove self so member function args start at index 1
562  // get member function from upvalue
563  RegType *l = static_cast<RegType*>(lua_touserdata(L, lua_upvalueindex(1)));
564  return (obj->*(l->mfunc))(L); // call member function
565  }
566 
567  // create a new T object and
568  // push onto the Lua stack a userdata containing a pointer to T object
569  static int new_T(lua_State *L) {
570  lua_remove(L, 1); // use classname:new(), instead of classname.new()
571  T *obj = new T(L); // call constructor for T objects
572  userdataType *ud =
573  static_cast<userdataType*>(lua_newuserdata(L, sizeof(userdataType)));
574  ud->pT = obj; // store pointer to object in userdata
575  luaL_getmetatable(L, T::className); // lookup metatable in Lua registry
576  lua_setmetatable(L, -2);
577  return 1; // userdata containing pointer to T object
578  }
579 
580  // garbage collection metamethod
581  static int gc_T(lua_State *L) {
582  userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1));
583  T *obj = ud->pT;
584  if ( obj )
585  {
586  delete obj; // call destructor for T objects
587  obj = 0;
588  }
589  return 0;
590  }
591 
592  static int tostring_T (lua_State *L) {
593  char buff[32];
594  userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1));
595  T *obj = ud->pT;
596  sprintf(buff, "%p", obj);
597  lua_pushfstring(L, "%s (%s)", T::className, buff);
598  return 1;
599  }
600  */
601 };
602 
603 #define DECLARE_SCRIPT_CLASS(ClassName) \
604  public: \
605  static const char className[]; \
606  static moLuna<ClassName>::PropertyType Properties[]; \
607  static moLuna<ClassName>::FunctionType Functions[];\
608 \
609  bool isExisting; \
610  bool isPrecious;
611 
612 
613 #define IMPLEMENT_SCRIPT_CLASS(ClassName) \
614  const char ClassName::className[] = #ClassName;
615 
616 #define DEFINE_SCRIPT_CLASS_FUNCTIONS(ClassName) \
617  moLuna<ClassName>::FunctionType ClassName::Functions[] = {
618 
619 #define SCRIPT_FUNCTION(ClassName, FunctionName) { #FunctionName, &ClassName::FunctionName }
620 
621 #define END_SCRIPT_CLASS_FUNCTIONS };
622 
623 
624 #define DEFINE_SCRIPT_CLASS_PROPERTIES(ClassName) \
625  moLuna<ClassName>::PropertyType ClassName::Properties[] = {
626 
627 #define SCRIPT_PROPERTY(ClassName, PropertyName, PropertyGetter, PropertySetter ) { #PropertyName, &ClassName::PropertyGetter, &ClassName::PropertySetter }
628 
629 #define END_SCRIPT_CLASS_PROPERTIES };
630 
631 #define REGISTER_CLASS(ClassName, LuaState) \
632  moLuna<ClassName>::Register(LuaState);
633 
634 #define SCRIPT_CONSTRUCTOR_DECLARATION(ClassName) ClassName(lua_State* L);
635 #define SCRIPT_CONSTRUCTOR_IMPLEMENTATION(ClassName) ClassName::ClassName(lua_State* L)
636 
637 #define SCRIPT_FUNCTION_DECLARATION(FunctionName) int FunctionName(lua_State* L);
638 #define SCRIPT_FUNCTION_IMPLEMENTATION(ClassName, FunctionName) int ClassName::FunctionName(lua_State* L)
639 
640 #endif
int(T::* setter)(lua_State *)
Definition: moLuna.h:79
static void Register(lua_State *L, const char *namespac="")
eso no esta en LunaFourCode
Definition: moLuna.h:237
static int constructor(lua_State *L)
LunaFourCode.
Definition: moLuna.h:274
static T * createFromExisting(lua_State *L, T *existingobj)
Definition: moLuna.h:384
static int property_getter(lua_State *L)
Definition: moLuna.h:435
static int gc_obj(lua_State *L)
Definition: moLuna.h:536
const char * name
Definition: moLuna.h:77
LunaFourCode.
Definition: moLuna.h:83
LunaFourCode.
Definition: moLuna.h:76
const char * name
Definition: moLuna.h:84
static T * createNew(lua_State *L)
Definition: moLuna.h:328
int(T::* getter)(lua_State *)
Definition: moLuna.h:78
LunaFourCode.
Definition: moLuna.h:68
static int property_setter(lua_State *L)
Definition: moLuna.h:476
static int function_dispatch(lua_State *L)
Definition: moLuna.h:516