Changeset 3858


Ignore:
Timestamp:
Mar 8, 2015, 12:39:16 AM (7 years ago)
Author:
touky
Message:

small lua code refactor

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/tutorial/14_lol_lua.cpp

    r3857 r3858  
    2020
    2121//-----------------------------------------------------------------------------
    22 class FooTest
     22class FooTestLua : public Lolua::ObjectDef
    2323{
    2424public:
    25     FooTest()
    26     {
    27     }
    28     static int New(Lolua::State* l)
    29     {
    30         int n_args = lua_gettop(l);  // Number of arguments
    31 
    32         // We could actually allocate Foo itself as a user data but
    33         // since user data can be GC'ed and we gain unity by using CRT's heap
    34         // all along.
    35         FooTest** udata = (FooTest**)lua_newuserdata(l, sizeof(FooTest*));
    36         *udata = new FooTest();
    37 
    38         // Usually, we'll just use "Foo" as the second parameter, but I
    39         // say luaL_Foo here to distinguish the difference:
    40         //
    41         // This 2nd parameter here is an _internal label_ for luaL, it is
    42         // _not_ exposed to Lua by default.
    43         //
    44         // Effectively, this metatable is not accessible by Lua by default.
    45         //luaL_getmetatable(l, m_table_name);
    46 
    47         // The Lua stack at this point looks like this:
    48         //     
    49         //     3| metatable "luaL_foo"   |-1
    50         //     2| userdata               |-2
    51         //     1| string parameter       |-3
    52         //
    53         // So the following line sets the metatable for the user data to the luaL_Foo
    54         // metatable
    55         //
    56         // We must set the metatable here because Lua prohibits setting
    57         // the metatable of a userdata in Lua. The only way to set a metatable
    58         // of a userdata is to do it in C.
    59         //lua_setmetatable(l, -2);
    60 
    61         luaL_getmetatable(l, m_table2_name);
    62         lua_setmetatable(l, -2);
    63 
    64         // The Lua stack at this point looks like this:
    65         //     
    66         //     2| userdata               |-1
    67         //     1| string parameter       |-2
    68         //
    69         // We return 1 so Lua callsite will get the user data and
    70         // Lua will clean the stack after that.
    71 
    72         return 1;
    73     }
    74     static FooTest* Check(Lolua::State* l, int n)
    75     {
    76         // This checks that the argument is a userdata
    77         // with the metatable "luaL_Foo"
    78         return *(FooTest**)luaL_testudata(l, n, m_table2_name);
    79     }
    80     static int Del(Lolua::State * l)
    81     {
    82         FooTest* foo = Check(l, 1);
    83         delete foo;
    84 
    85         return 0;
    86     }
    87     static void Register(Lolua::State * l)
    88     {
    89         // Create a luaL metatable. This metatable is not
    90         // exposed to Lua. The "luaL_Foo" label is used by luaL
    91         // internally to identity things.
    92         luaL_newmetatable(l, m_table2_name);
    93         luaL_setfuncs(l, FooTest::m_statics2, 0);
    94         lua_pushvalue(l, -1);
    95         lua_setfield(l, -1, "__index");
    96         //lua_setglobal(l, m_class2_name);
    97         lua_pop(l, 1);
    98 
    99         // Create a luaL metatable. This metatable is not
    100         // exposed to Lua. The "luaL_Foo" label is used by luaL
    101         // internally to identity things.
    102         luaL_newmetatable(l, m_table_name);
    103 
    104         // Register the C functions _into_ the metatable we just created.
    105         luaL_setfuncs(l, FooTest::m_statics, 0);
    106 
    107         // The Lua stack at this point looks like this:
    108         //     
    109         //     1| metatable "luaL_Foo"   |-1
    110         lua_pushvalue(l, -1);
    111 
    112         // The Lua stack at this point looks like this:
    113         //     
    114         //     2| metatable "luaL_Foo"   |-1
    115         //     1| metatable "luaL_Foo"   |-2
    116 
    117         // Set the "__index" field of the metatable to point to itself
    118         // This pops the stack
    119         lua_setfield(l, -1, "__index");
    120 
    121         // The Lua stack at this point looks like this:
    122         //     
    123         //     1| metatable "luaL_Foo"   |-1
    124 
    125         // The luaL_Foo metatable now has the following fields
    126         //     - __gc
    127         //     - __index
    128         //     - new
    129 
    130         // Now we use setglobal to officially expose the luaL_Foo metatable
    131         // to Lua. And we use the name "Foo".
    132         //
    133         // This allows Lua scripts to _override_ the metatable of Foo.
    134         // For high security code this may not be called for but
    135         // we'll do this to get greater flexibility.
    136         lua_setglobal(l, m_class_name);
    137     }
    138     static int Test1(Lolua::State* L)
    139     {
    140         Lolua::Var<int> i1(L, 1);
    141         i1 += 5;
    142         return i1.Return(L);
    143     }
    144     static int Test2(Lolua::State* L)
    145     {
    146         FooTest* foo = Check(L, 1);
    147         Lolua::Var<float> i1(L, 2);
    148         i1 = foo->Test2Inst(i1.V());
    149         return i1.Return(L);
    150     }
    151     float Test2Inst(float f)
    152     {
    153         return (f + 10);
    154     }
    155 
    156     static const char m_class_name[];
    157     static const char m_class2_name[];
    158     static const char m_table_name[];
    159     static const char m_table2_name[];
    160     static const luaL_Reg m_statics[];
    161     static const luaL_Reg m_statics2[];
    162     static const luaL_Reg m_methods[];
    163 };
    164 
    165 const luaL_Reg FooTest::m_statics[] = {
    166     { "New", &FooTest::New },
    167     { "__gc", &FooTest::Del },
    168     { "Test1", &FooTest::Test1 },
    169     { NULL, NULL } };
    170 const luaL_Reg FooTest::m_statics2[] = {
    171     { "Test2", &FooTest::Test2 },
    172     { NULL, NULL } };
    173 const luaL_Reg FooTest::m_methods[] = { { NULL, NULL } };
    174 const char     FooTest::m_class_name[] = "FooTest";
    175 const char     FooTest::m_class2_name[] = "FooTest2";
    176 const char     FooTest::m_table_name[] = "FooTest_mt";
    177 const char     FooTest::m_table2_name[] = "FooTest_mt2";
    178 
    179 typedef Lolua::ObjectDef<FooTest> FooTestLuaBase;
    180 class FooTestLua : public FooTestLuaBase
    181 {
    182 public:
    183     FooTestLua() : FooTestLuaBase() {}
     25    FooTestLua() : Lolua::ObjectDef() {}
    18426    virtual ~FooTestLua() {}
    18527    static FooTestLua* New(Lolua::State* l, int arg_nb)
     
    25698        uint32_t TestValueUint = demo_loader->GetVar<uint32_t>("TestValueUint");
    25799        String TestValueStr = demo_loader->GetVar<String>("TestValueStr");
    258         //String test_return2 = demo_loader->GetVar<String>("test_return2");
    259         //String test_return3 = demo_loader->GetVar<String>("test_return3");
    260100        int32_t testtruc_return = demo_loader->GetVar<int32_t>("footest_return");
    261101        float testtruc_return2 = demo_loader->GetVar<float>("footest_return2");
    262         //int32_t testtruc2_return = demo_loader->GetVar<int32_t>("testtruc_return2");
    263102
    264103        String::Printf("Lua Vars: TestValueNum: %.2f, TestValueInt: %i, TestValueUint: %i, TestValueStr: %s.",
  • trunk/src/application/baselua.h

    r3857 r3858  
    2929
    3030//-----------------------------------------------------------------------------
    31 template <typename T>
    3231class ObjectDef
    3332{
     
    3534    ObjectDef() { }
    3635    virtual ~ObjectDef() { }
    37     static ObjectDef<T>* New(State* l, int arg_nb)
     36    static ObjectDef* New(State* l, int arg_nb)
    3837    {
    3938        UNUSED(l);
     
    4746    static const ClassMethod* GetStaticMethods()    { ASSERT(false); return nullptr; }
    4847    static const ClassMethod* GetInstanceMethods()  { ASSERT(false); return nullptr; }
    49 
    50 protected:
    51     T* m_instance = nullptr;
    5248};
    5349
     
    286282};
    287283
    288 //-----------------------------------------------------------------------------
    289 //class T definition
    290 //class T
    291 //{
    292 //public:
    293 //      int Ctor(lua_State* l) { return 0; }
    294 //      static const char*                  m_class_name;
    295 //      static const Class<T>::Variable*    m_variables;
    296 //      static const Class<T>::Method*      m_methods;
    297 //};
    298 /*
    299 //-----------------------------------------------------------------------------
    300 template<typename T>
    301 class ClassTest
    302 {
    303 public:
    304     //-----------------------------------------------------------------------------
    305     struct Variable
    306     {
    307         const char*             m_name;
    308         int(*Getter)(lua_State*);
    309         int(*Setter)(lua_State*);
    310     };
    311 
    312     //-----------------------------------------------------------------------------
    313     struct Method
    314     {
    315         const char*             m_name;
    316         int(*Func)(lua_State*);
    317     };
    318 
    319     //Register: Register class in Lua. Leave library empty to store class in global scope.
    320     static void Register(lua_State* l, const char *library = NULL)
    321     {
    322         if (library && strlen(library))
    323         {
    324             lua_getglobal(l, library);
    325             //Create library if not present
    326             if (lua_isnil(l, -1))
    327             {
    328                 lua_newtable(l);
    329                 //Duplicate table pointer since setglobal pops the value
    330                 lua_pushvalue(l, -1);
    331                 lua_setglobal(l, library);
    332             }
    333             //lua_pushcfunction(l, &Class<T>::Ctor);
    334             //lua_setfield(l, -2, T::m_class_name);
    335             //lua_pop(l, 1);
    336         }
    337         else
    338         {
    339             //lua_pushcfunction(l, &Class<T>::Ctor);
    340             //lua_setglobal(l, T::m_class_name);
    341         }
    342 
    343         luaL_newmetatable(l, T::m_class_name);
    344         int metatable = lua_gettop(l);
    345 
    346         //Register all m_methods: Register Name for fun_call and number for choice
    347         for (int i = 0; T::m_methods[i].m_name; i++)
    348         {
    349             lua_pushstring(l, T::m_methods[i].m_name);
    350             lua_pushcfunction(l, T::m_methods[i].Func);
    351             lua_settable(l, metatable);
    352         }
    353 
    354         //lua_pushstring(l, "__gc");
    355         //lua_pushcfunction(l, &Class<T>::Dtor);
    356         //lua_settable(l, metatable);
    357 
    358         //lua_pushstring(l, "__tostring");
    359         //lua_pushcfunction(l, &Class<T>::ToString);
    360         //lua_settable(l, metatable);
    361 
    362         //lua_pushstring(l, "__eq");
    363         //lua_pushcfunction(l, &Class<T>::Equals);
    364         //lua_settable(l, metatable);
    365 
    366         //lua_pushstring(l, "__index");
    367         //lua_pushcfunction(l, &Class<T>::Getter);
    368         //lua_settable(l, metatable);
    369 
    370         //lua_pushstring(l, "__newindex");
    371         //lua_pushcfunction(l, &Class<T>::Setter);
    372         //lua_settable(l, metatable);
    373 
    374         ////Register all properties: Register Name for fun_call and number for choice
    375         //for (int i = 0; T::m_variables[i].m_name; i++)
    376         //{
    377         //    lua_pushstring(l, T::m_variables[i].m_name);
    378         //    lua_pushnumber(l, i);
    379         //    lua_settable(l, metatable);
    380         //}
    381 
    382         ////Register all m_methods: Register Name for fun_call and number for choice
    383         //for (int i = 0; T::m_methods[i].m_name; i++)
    384         //{
    385         //    lua_pushstring(l, T::m_methods[i].m_name);
    386         //    //Add (1 << 8) to identify function on call
    387         //    lua_pushnumber(l, i | (1 << 8));
    388         //    lua_settable(l, metatable);
    389         //}
    390     }
    391 
    392 };
    393 
    394 //-----------------------------------------------------------------------------
    395 template<typename T>
    396 class Class
    397 {
    398 public:
    399     //-----------------------------------------------------------------------------
    400     struct Variable
    401     {
    402         const char*             m_name;
    403         int             (T::*Getter)(lua_State*);
    404         int             (T::*Setter)(lua_State*);
    405     };
    406 
    407     //-----------------------------------------------------------------------------
    408     struct Method
    409     {
    410         const char*             m_name;
    411         int             (T::*Func)(lua_State*);
    412     };
    413 
    414     //-----------------------------------------------------------------------------
    415     //Check: Raise an exception if FAIL
    416     static T* Check(lua_State * l, int narg)
    417     {
    418         T** obj = static_cast <T **>(luaL_checkudata(l, narg, T::m_class_name));
    419         return !obj ? nullptr : *obj;
    420     }
    421 
    422     //LightCheck: Returns nullptr if FAIL
    423     static T* LightCheck(lua_State* l, int num_args)
    424     {
    425         T** obj = static_cast <T **>(luaL_testudata(l, num_args, T::m_class_name));
    426         return !obj ? nullptr : *obj;
    427     }
    428 
    429     //Register: Register class in Lua. Leave library empty to store class in global scope.
    430     static void Register(lua_State* l, const char *library = NULL)
    431     {
    432         if (library && strlen(library))
    433         {
    434             lua_getglobal(l, library);
    435             //Create library if not present
    436             if (lua_isnil(l, -1))
    437             {
    438                 lua_newtable(l);
    439                 //Duplicate table pointer since setglobal pops the value
    440                 lua_pushvalue(l, -1);
    441                 lua_setglobal(l, library);
    442             }
    443             lua_pushcfunction(l, &Class<T>::Ctor);
    444             lua_setfield(l, -2, T::m_class_name);
    445             lua_pop(l, 1);
    446         }
    447         else
    448         {
    449             lua_pushcfunction(l, &Class<T>::Ctor);
    450             lua_setglobal(l, T::m_class_name);
    451         }
    452 
    453         luaL_newmetatable(l, T::m_class_name);
    454         int metatable = lua_gettop(l);
    455 
    456         //lua_pushstring(l, "__gc");
    457         //lua_pushcfunction(l, &Class<T>::Dtor);
    458         //lua_settable(l, metatable);
    459 
    460         //lua_pushstring(l, "__tostring");
    461         //lua_pushcfunction(l, &Class<T>::ToString);
    462         //lua_settable(l, metatable);
    463 
    464         //lua_pushstring(l, "__eq");
    465         //lua_pushcfunction(l, &Class<T>::Equals);
    466         //lua_settable(l, metatable);
    467 
    468         lua_pushstring(l, "__index");
    469         lua_pushcfunction(l, &Class<T>::Getter);
    470         lua_settable(l, metatable);
    471 
    472         lua_pushstring(l, "__newindex");
    473         lua_pushcfunction(l, &Class<T>::Setter);
    474         lua_settable(l, metatable);
    475 
    476         //Register all properties: Register Name for fun_call and number for choice
    477         for (int i = 0; T::m_variables[i].m_name; i++)
    478         {
    479             lua_pushstring(l, T::m_variables[i].m_name);
    480             lua_pushnumber(l, i);
    481             lua_settable(l, metatable);
    482         }
    483 
    484         //Register all m_methods: Register Name for fun_call and number for choice
    485         for (int i = 0; T::m_methods[i].m_name; i++)
    486         {
    487             lua_pushstring(l, T::m_methods[i].m_name);
    488             //Add (1 << 8) to identify function on call
    489             lua_pushnumber(l, i | (1 << 8));
    490             lua_settable(l, metatable);
    491         }
    492     }
    493 
    494 private:
    495     //Ctor
    496     static int Ctor(lua_State* l)
    497     {
    498         T*  obj = new T(l);
    499         T** lua_obj = static_cast<T**>(lua_newuserdata(l, sizeof(T*))); // Push value = userdata
    500         *lua_obj = obj;
    501 
    502         luaL_getmetatable(l, T::m_class_name);          // Fetch global metatable T::classname
    503         lua_setmetatable(l, -2);
    504         return 1;
    505     }
    506 
    507     //Dtor
    508     static int Dtor(lua_State* l)
    509     {
    510         T** lua_obj = static_cast<T**>(lua_touserdata(l, -1));
    511         if (lua_obj && *lua_obj)
    512             delete(*lua_obj);
    513         return 0;
    514     }
    515 
    516     //AddInstance
    517     static void AddInstance(lua_State* l, T* instance)
    518     {
    519         T** a = (T**)lua_newuserdata(l, sizeof(T*)); // Create userdata
    520         *a = instance;
    521 
    522         luaL_getmetatable(l, T::m_class_name);
    523         lua_setmetatable(l, -2);
    524     }
    525 
    526     //----
    527     static void GetVarIndex(lua_State* l)
    528     {
    529         lua_getmetatable(l, 1); //Look up the index of a m_name
    530         lua_pushvalue(l, 2);    //Push the m_name
    531         lua_rawget(l, -2);              //Get the index
    532     }
    533 
    534     //----
    535     static void PrepareGetSet(lua_State* l)
    536     {
    537         lua_pop(l, 2);    // Pop metatable and idx
    538         lua_remove(l, 1); // Remove userdata
    539         lua_remove(l, 1); // Remove [key]
    540     }
    541 
    542     //Getter: Call a func or a getter var
    543     static int Getter(lua_State* l)
    544     {
    545         GetVarIndex(l);
    546         //Check if we got a valid index
    547         if (lua_isnumber(l, -1))
    548         {
    549             int idx = lua_tonumber(l, -1);
    550             T** obj = static_cast<T**>(lua_touserdata(l, 1));
    551             lua_pushvalue(l, 3);
    552 
    553             //It's a method
    554             if (idx & (1 << 8))
    555             {
    556                 //Push the Method index and call the function
    557                 lua_pushnumber(l, idx ^ (1 << 8));
    558                 lua_pushlightuserdata(l, obj);
    559                 lua_pushcclosure(l, &Class<T>::CallMethod, 2);
    560                 // Return a Method
    561                 return 1;
    562             }
    563             else
    564             {
    565                 PrepareGetSet(l);
    566                 return ((*obj)->*(T::m_variables[idx].Getter))(l);
    567             }
    568         }
    569         return 1;
    570     }
    571 
    572     //Getter: Class a setter var or error if func
    573     static int Setter(lua_State* l)
    574     {
    575         GetVarIndex(l);
    576         //Check if we got a valid index
    577         if (lua_isnumber(l, -1))
    578         {
    579             int idx = lua_tonumber(l, -1);
    580             T** obj = static_cast<T**>(lua_touserdata(l, 1));
    581             if (!obj || !*obj)
    582             {
    583                 luaL_error(l, "Internal error, no object given!");
    584                 return 0;
    585             }
    586 
    587             //Try to set a Method - FAIL
    588             if (idx & (1 << 8))
    589             {
    590                 String s = String::Printf("Trying to set the method [%s] of class [%s]", (*obj)->T::m_methods[idx ^ (1 << 8)].m_name, T::m_class_name);
    591                 luaL_error(l, s.C());
    592                 return 0;
    593             }
    594             else
    595             {
    596                 PrepareGetSet(l);
    597                 return ((*obj)->*(T::m_variables[idx].Setter))(l);
    598             }
    599         }
    600         return 0;
    601     }
    602 
    603     //CallMethod: Actually calls the method on the object
    604     static int CallMethod(lua_State* l)
    605     {
    606         int i = (int)lua_tonumber(l, lua_upvalueindex(1));
    607         T** obj = static_cast <T**>(lua_touserdata(l, lua_upvalueindex(2)));
    608         return ((*obj)->*(T::m_methods[i].Func))(l);
    609     }
    610 
    611     //ToString:
    612     static int ToString(lua_State* l)
    613     {
    614         T** obj = static_cast<T**>(lua_touserdata(l, -1));
    615         if (obj)
    616             lua_pushfstring(l, "%s (%p)", T::m_class_name, (void*)*obj);
    617         else
    618             lua_pushstring(l, "Empty object");
    619         return 1;
    620     }
    621 
    622     //Equals:
    623     static int Equals(lua_State* l)
    624     {
    625         T** obj1 = static_cast<T**>(lua_touserdata(l, -1));
    626         T** obj2 = static_cast<T**>(lua_touserdata(l, 1));
    627         lua_pushboolean(l, *obj1 == *obj2);
    628         return 1;
    629     }
    630 };
    631 */
    632 
    633284} /* namespace Lolua */
    634285
Note: See TracChangeset for help on using the changeset viewer.