c++castinglualuabindlua-api

How does luabind implicitly cast objects?


Without going into too many irrelevant details about a large multi-library project I'm working on I'd like to ask a question about a specific event that occurred in it. I'm using Luabind to have my C++ code interface with my Lua code and I have a class structure with inheritance like so:

GuiWidget

GuiButton : GuiWidget

I've registered both of these classes with Lua via Luabind. Then I do the following, where widget is a pointer to an instance of the GuiWidget class:

lua_newtable(luaState);
luabind::object(luaState, widget).push(luaState);
lua_setfield(luaState, 2, "widget");
lua_setglobal(luaState, "event");
//This line connects to some other code I wrote that just executes a file and handles errors.
luaMachine->doFile(widget->getUserString("eventMouseButtonClick"));
lua_pushnil(luaState);
lua_setglobal(luaState, "event");

Now this same code snippet can handle anything from buttons to scroll bars and even entire windows. So later on in the lua code I call this line of code for when a check box button is clicked:

event.widget:setSelected(not event.widget:getSelected())

This works. Even though the pointer pushed through is a GuiWidget pointer the lua code somehow knows to use functionality unique to GuiButton class for this particular instance. How does it do that? How does it take a widget pointer and automatically know that particular widget is a button? I didn't believe it was possible so it took me a while to arrive at that solution but I figured I'd take a shot in the dark and it worked somehow.


Solution

  • It has been a long time since you asked but i may have an answer for this...

    1. luabind generates internal unique ID for every type you register when you start your executable (+ wrappers etc...)
    2. There is global "map" in LUA_REGISTRYINDEX called __luabind_class_id_map translating typeid to this previously assigned internal unique ID
    3. When you return pointer (GuiWidget) luabind asks for typeid of returned pointer by dereferencing it -> typeid(ptr). This surprisingly returns type_info of GuiButton not GuiWidget (although GuiWidget ptr = new GuiButton();)
    4. Then luabind translates typeid of GuiButton into internal ID and finds class_rep for that in another LUA_REGISTRYINDEX table (__luabind_class_map). class_rep holds how object should be stored on Lua side and other info related to registered c++ class.

    Last interesting info for making this to work is, that all pointers on Lua side are stored like so: dynamic_cast(ptr) that later allows for auto casting from that to other classes validated using previous method and inheritance info in class_rep

    That is roughly how this implicit casting can be done / is done in luabind library.