2

在不涉及我正在处理的大型多图书馆项目的太多无关细节的情况下,我想问一个关于其中发生的特定事件的问题。我正在使用 Luabind 让我的 C++ 代码与我的 Lua 代码接口,并且我有一个具有继承的类结构,如下所示:

GuiWidget

GuiButton : GuiWidget

我已经通过 Luabind 向 Lua 注册了这两个类。然后我执行以下操作,指向类widget实例的指针在哪里GuiWidget

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");

现在,同样的代码片段可以处理从按钮到滚动条甚至整个窗口的任何内容。因此,稍后在 lua 代码中,当单击复选框按钮时,我将这行代码称为:

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

这行得通。即使推送的指针是一个GuiWidget指针,lua 代码也知道要使用GuiButton该特定实例的类独有的功能。它是如何做到的?它如何获取一个小部件指针并自动知道特定的小部件是一个按钮?我不相信这是可能的,所以我花了一段时间才找到那个解决方案,但我想我会在黑暗中拍摄,它以某种方式起作用。

4

1 回答 1

1

很久没问了,但我可能有答案...

  1. luabind 为您在启动可执行文件时注册的每种类型生成内部唯一 ID(+ 包装器等...)
  2. LUA_REGISTRYINDEX 中有一个名为 __luabind_class_id_map 的全局“映射”,将 typeid 转换为先前分配的内部唯一 ID
  3. 当你返回指针(GuiWidget)时,luabind 通过取消引用它来请求返回指针的 typeid -> typeid( ptr)。这令人惊讶地返回 GuiButton 的 type_info 而不是 GuiWidget(尽管 GuiWidget ptr = new GuiButton();)
  4. 然后 luabind 将 GuiButton 的 typeid 转换为内部 ID,并在另一个 LUA_REGISTRYINDEX 表 (__luabind_class_map) 中找到它的 class_rep。class_rep 保存对象应如何存储在 Lua 端以及与注册的 c++ 类相关的其他信息。

使它工作的最后一个有趣的信息是,Lua 端的所有指针都这样存储:dynamic_cast(ptr),稍后允许从该类自动转换到使用先前方法和 class_rep 中的继承信息验证的其他类

这大致就是在 luabind 库中如何完成这种隐式转换。

于 2019-01-11T22:05:19.053 回答