lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I wasn't enough clear so I'm going to start from the beginning.
Here is what I want to do : register classes with their attributes, properties and functions.
I have a reflexivity system so no problème do dynamcly create the tables.
Here's what I do (I'm not really sure for all the step. I don't think I really get the whole thing of how works the metatables).

So, when I want to register a class, I call this function :

void gnScriptEngine::RegisterMetaType(gnMetaType const& a_rMetaType)
{
  
    gnMetaClass const& rMetaClass = a_rMetaType.GetMetaClass(); //Get the class

    gnPrintA oPrint;
    gnSzA szClassName = gnStrConvert(rMetaClass.GetName().Sz(), oPrint); //Get the class name

    // MetaTable = {}
    luaL_newmetatable(m_pState, szClassName);  //Create the main metatable of the classe
    int iMetaTable = lua_gettop(m_pState);

    // MetaTable.__index = MethodTable
    lua_pushliteral(m_pState, "__index");                    // MetaTable "__index"
    lua_pushvalue(m_pState, iMetaTable);                    // MetaTable "__index" MetaTable
    lua_settable(m_pState, iMetaTable);                        // MetaTable

    // MetaTable.__gc = gc_account
    lua_pushliteral(m_pState, "__gc");                        // MetaTable "__gc"
    lua_pushcfunction(m_pState, GarbageCollecting);            // MetaTable "__gc" GarbageCollecting
    lua_settable(m_pState, iMetaTable);                        // MetaTable

    // MetaTable.__tostring = ToString
    lua_pushliteral(m_pState, "__tostring");                // MetaTable "__tostring"
    lua_pushcfunction(m_pState, ToString);                    // MetaTable "__tostring" ToString
    lua_settable(m_pState, iMetaTable);                        // MetaTable

    gnMetaFieldVector vMetaFields;
    rMetaClass.GetAllMetaFields(vMetaFields); //Get all the attributes of the class

    GN_FOREACH_IT_CONST(gnMetaFieldVector, vMetaFields, it) // == for each
    {
        gnIMetaField const& rMetaField = **it;
       
        gnPrintA oPrint;
        gnSzA szFieldName = gnStrConvert(rMetaField.GetName().Sz(), oPrint); //Get the name of the attribute

        //Push the name of the field (the key in the iMetaTable)
        lua_pushstring(m_pState, szFieldName); //push the name onto the stack
       
        //Create a new closure for each field
        gnPseudoField* pPseudoField = (gnPseudoField*)lua_newuserdata(m_pState, sizeof(gnPseudoField)); //create a new userdata from the pseudoField containing the attribute and its type
        gnAssertBase(pPseudoField != NULL, 0x4AA40200, "Allocation of new user data failed");
        pPseudoField->m_rMetaField = rMetaField; 
        pPseudoField->m_oMetaType = rMetaField.GetValueType();

        lua_pushcfunction(m_pState, DispatchField);    //push the function DispatchField onto the stack (this function do a get or a set depending of the stack)
        lua_settable(m_pState, iMetaTable);   //affecte it to the metatable
    }

    vMetaFields.Clear(); //clear the list

    gnMetaMethodVector vMetaMethods;

    rMetaClass.GetAllMetaMethods(vMetaMethods); //get all the methods of the class

    GN_FOREACH_IT_CONST(gnMetaMethodVector, vMetaMethods, it) // == for each
    {
        gnIMetaMethod const& rMetaMethod = gnMetaClass::GetMetaMethod(it); get the method

        gnPrintA oPrint;
        gnSzA szMethodName = gnStrConvert(rMetaMethod.GetName().Sz(), oPrint); //get the name of the method

        lua_pushstring(m_pState, szMethodName);  //push the name onto the stack

        // Create a new closure for each method (with the gnMetaMethod in it)
        gnPseudoMethod* pPseudoMethod = (gnPseudoMethod*)lua_newuserdata(m_pState, sizeof(gnPseudoMethod)); //create a new userdata from pseudoMethod containing the method
        gnAssertBase(pPseudoMethod != NULL, 0x64E80200, "Allocation of new user data failed");
        pPseudoMethod->m_rMetaMethod = rMetaMethod; 
        lua_pushcclosure(m_pState, DispatchMethod, 1);  //push the function DispatchMethod onto the stack (this function call the method)
       
        // Affect the entry in the iMetaTable, and pop key and value
        lua_settable(m_pState, iMetaTable);                
    }

    vMetaMethods.Clear();

    // Drop MetaTable
    lua_pop(m_pState, 1);                                 

    // Constructor
    gnBoxedMetaType* pBoxedMetaType = (gnBoxedMetaType*)lua_newuserdata(m_pState, sizeof(gnBoxedMetaType));
    gnAssertBase(pBoxedMetaType != NULL, 0x58500200, "Allocation of new user data failed");
    pBoxedMetaType->m_oMetaType = a_rMetaType;
    lua_pushcclosure(m_pState, New, 1);
    lua_setglobal(m_pState, szClassName);

Finish !
So, all work but not the myObject.myAttribute.
When I try to call "myObject.myAttribute, the DispatchField method is nerver called :(