2

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.

Community
  • 1
  • 1
Jake Kiesel
  • 341
  • 4
  • 10
  • 1
    Is the function virtual? If so it doesn't have to know, just calling the virtual function will execute the derived class's implementation. – David Brown Dec 10 '14 at 01:38
  • No it's not virtual, I checked my libraries documentation and this function only exists in the GuiButton class – Jake Kiesel Dec 10 '14 at 07:55
  • There is a link to the doc? – greatwolf Dec 10 '14 at 09:56
  • https://github.com/MyGUI/mygui/tree/master/MyGUIEngine/src this is the source folder for the library I'm using. MyGUI::Widget and MyGUI::Button are the classes I'm using. The function being called is setStateSelected however I took some liberty with the Lua side of things and called them GuiWidget and GuiButton with function setSelected. – Jake Kiesel Dec 10 '14 at 13:17
  • https://github.com/MyGUI/mygui/tree/master/MyGUIEngine/include these are the header files, which are probably more useful for an overview look. – Jake Kiesel Dec 10 '14 at 13:24

1 Answers1

1

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.

sadovsf
  • 58
  • 6