Assign a C++ function to a global lua variable

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Assign a C++ function to a global lua variable

Teto
Hi folks,

I want to overwrite the __newindex method for a certain type of class from the C++ side (to prevent creation of new properties without me noticing it, it prevents me from mistyping variables).

Here is as far as  I go:
bool
CLuaVM::setSpecialNewIndex(const char* class_name){

    luabind::object obj = get_class_names( getVM() );
    luabind::object mt = getmetatable(obj[class_name]);

    mt["__newindex"] = specialNewIndex; // specialNewIndex should be the function called when __newindex is called from lua for that class
}

It's late here so maybe that's why I miss something.

Matt

------------------------------------------------------------------------------
vRanger cuts backup time in half-while increasing security.
With the market-leading solution for virtual backup and recovery,
you get blazing-fast, flexible, and affordable data protection.
Download your free trial now.
http://p.sf.net/sfu/quest-d2dcopy1
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: Assign a C++ function to a global lua variable

Teto
Here is my current function to overwrite the global metatable (doesn't seem possible to create a metatable per type_id) , everything is ok it works (I put it there for other people interested):
bool
CLuaVM::setSpecialNewIndex(){


    luabind::detail::class_registry* reg  = detail::class_registry::get_registry( _vm );
// with templates you could possibly set a metamethod per class_rep, but right now any type actually registered can be used to access the generic metatable
    luabind::detail::class_rep* rep = reg->find_class( typeid(irr::SIrrlichtCreationParameters) );

    if(!rep){
        _LOG_WARNING << "could not find a class re for this type";
        return false;
    }
    else {
        _INFO << "found rep for class '" << rep->name() << "'";
    }
    int index = rep->metatable_ref();


    // voici la cle utilise pour acceder au tableau representant la metatable
    lua_pushinteger( _vm, index );
    // Pushes on top of stack the metatable
    lua_gettable(_vm, LUA_REGISTRYINDEX);
    lua_pushstring( _vm , "__newindex");
    //   Here I set my own __newindex function replacing the default one aka class_rep::lua_settable_dispatcher
    lua_pushcclosure(_vm, &onNewIndex, 0);
    lua_rawset( _vm, -3);

    // pop metatable
    lua_pop( _vm,1);
    return true;
}

In fact for the moment my onNewIndex function is exactly the same as the one provided by default (I put it so that you don't have to look for it)
int onNewIndex(lua_State *L) {

    //If the value at the given acceptable index is a full userdata, returns its block address. If the value is a light userdata, returns its pointer. Otherwise, returns NULL.
    detail::class_rep* crep = static_cast<detail::class_rep*>(lua_touserdata( L, 1));


    crep->get_table(L);

    // copy key, then value
    lua_pushvalue(L, -3);
    lua_pushvalue(L, -3);
    lua_rawset(L, -3);

    // pop table
    lua_pop(L, 1);

    // get default table
    crep->get_default_table(L);
    lua_replace(L, 1);
    lua_rawset(L, -3);

    return 0;
}


This function __newindex is called on the only line of my script "config.lua" which is:
EngineConfig.DriverType  = 5;

EngineConfig is a global registered from C++ (everything works if I don't change the luabind metatable):
    luabind::object globals;
    script.getGlobals(globals);
    globals["EngineConfig"]     = &engineParam;

The call to my personalized __newindex function crashes because crep->get_table(L);  and crep->get_default_table(L); both push nil on the stack instead of tables. Why is that ?

I know this is a long mail but if you could give me a hint please. I've already spent a lot of time on this.

matt

nb : Here is how I bind things:
    luabind::class_<irr::SIrrlichtCreationParameters>("SIrrlichtCreationParameters")
        .def_readwrite("DriverType",&SIrrlichtCreationParameters::DriverType)
        .enum_("DriverTypes")
            [
                value("opengl", video::EDT_OPENGL),
                value("directx8",video::EDT_DIRECT3D8),
                value("directx9",video::EDT_DIRECT3D9),
                value("software",video::EDT_BURNINGSVIDEO)
            ]



On Thu, May 26, 2011 at 1:11 AM, Teto <[hidden email]> wrote:
Hi folks,

I want to overwrite the __newindex method for a certain type of class from the C++ side (to prevent creation of new properties without me noticing it, it prevents me from mistyping variables).

Here is as far as  I go:
bool
CLuaVM::setSpecialNewIndex(const char* class_name){

    luabind::object obj = get_class_names( getVM() );
    luabind::object mt = getmetatable(obj[class_name]);

    mt["__newindex"] = specialNewIndex; // specialNewIndex should be the function called when __newindex is called from lua for that class
}

It's late here so maybe that's why I miss something.

Matt


------------------------------------------------------------------------------
vRanger cuts backup time in half-while increasing security.
With the market-leading solution for virtual backup and recovery,
you get blazing-fast, flexible, and affordable data protection.
Download your free trial now.
http://p.sf.net/sfu/quest-d2dcopy1
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: Assign a C++ function to a global lua variable

Teto
I think I've found what was wrong: the metatable I wanted to copy was not the one from the registry (lua_settable_dispatcher) but the one from object_rep (set_instance_value)

In fact what I (but that would useful for everyone) would be interested in is a little explanation (on the website maybe) about luabind inner workings. Indeed, there are very few comments and I find it hard to understand what's going on.
I've understood the binding process (additive scopes, one class_rep shared between object_rep, copy of base classes tables) I think but I'm a bit lost at runtime and at how metatbles are used (I have yet to understand what's the point of :lua_settable_dispatcher). When we access via globals["key"] = value; it creates an object_rep with its own metatable.

Well when I succeed in making my global instance readonly (should be soon) I will send a link as how to do it.

On Sun, May 29, 2011 at 3:56 AM, Teto <[hidden email]> wrote:
Here is my current function to overwrite the global metatable (doesn't seem possible to create a metatable per type_id) , everything is ok it works (I put it there for other people interested):
bool
CLuaVM::setSpecialNewIndex(){


    luabind::detail::class_registry* reg  = detail::class_registry::get_registry( _vm );
// with templates you could possibly set a metamethod per class_rep, but right now any type actually registered can be used to access the generic metatable
    luabind::detail::class_rep* rep = reg->find_class( typeid(irr::SIrrlichtCreationParameters) );

    if(!rep){
        _LOG_WARNING << "could not find a class re for this type";
        return false;
    }
    else {
        _INFO << "found rep for class '" << rep->name() << "'";
    }
    int index = rep->metatable_ref();


    // voici la cle utilise pour acceder au tableau representant la metatable
    lua_pushinteger( _vm, index );
    // Pushes on top of stack the metatable
    lua_gettable(_vm, LUA_REGISTRYINDEX);
    lua_pushstring( _vm , "__newindex");
    //   Here I set my own __newindex function replacing the default one aka class_rep::lua_settable_dispatcher
    lua_pushcclosure(_vm, &onNewIndex, 0);
    lua_rawset( _vm, -3);

    // pop metatable
    lua_pop( _vm,1);
    return true;
}

In fact for the moment my onNewIndex function is exactly the same as the one provided by default (I put it so that you don't have to look for it)
int onNewIndex(lua_State *L) {

    //If the value at the given acceptable index is a full userdata, returns its block address. If the value is a light userdata, returns its pointer. Otherwise, returns NULL.
    detail::class_rep* crep = static_cast<detail::class_rep*>(lua_touserdata( L, 1));


    crep->get_table(L);

    // copy key, then value
    lua_pushvalue(L, -3);
    lua_pushvalue(L, -3);
    lua_rawset(L, -3);

    // pop table
    lua_pop(L, 1);

    // get default table
    crep->get_default_table(L);
    lua_replace(L, 1);
    lua_rawset(L, -3);

    return 0;
}


This function __newindex is called on the only line of my script "config.lua" which is:
EngineConfig.DriverType  = 5;

EngineConfig is a global registered from C++ (everything works if I don't change the luabind metatable):
    luabind::object globals;
    script.getGlobals(globals);
    globals["EngineConfig"]     = &engineParam;

The call to my personalized __newindex function crashes because crep->get_table(L);  and crep->get_default_table(L); both push nil on the stack instead of tables. Why is that ?

I know this is a long mail but if you could give me a hint please. I've already spent a lot of time on this.

matt

nb : Here is how I bind things:
    luabind::class_<irr::SIrrlichtCreationParameters>("SIrrlichtCreationParameters")
        .def_readwrite("DriverType",&SIrrlichtCreationParameters::DriverType)
        .enum_("DriverTypes")
            [
                value("opengl", video::EDT_OPENGL),
                value("directx8",video::EDT_DIRECT3D8),
                value("directx9",video::EDT_DIRECT3D9),
                value("software",video::EDT_BURNINGSVIDEO)
            ]




On Thu, May 26, 2011 at 1:11 AM, Teto <[hidden email]> wrote:
Hi folks,

I want to overwrite the __newindex method for a certain type of class from the C++ side (to prevent creation of new properties without me noticing it, it prevents me from mistyping variables).

Here is as far as  I go:
bool
CLuaVM::setSpecialNewIndex(const char* class_name){

    luabind::object obj = get_class_names( getVM() );
    luabind::object mt = getmetatable(obj[class_name]);

    mt["__newindex"] = specialNewIndex; // specialNewIndex should be the function called when __newindex is called from lua for that class
}

It's late here so maybe that's why I miss something.

Matt



------------------------------------------------------------------------------
vRanger cuts backup time in half-while increasing security.
With the market-leading solution for virtual backup and recovery,
you get blazing-fast, flexible, and affordable data protection.
Download your free trial now.
http://p.sf.net/sfu/quest-d2dcopy1
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user