使用 Toluapp 实现虚拟方法 |
|
需要 2 个文件
文件:wiki_insecure/users/ArielManzur/tolua++/virtual_method_hooks.lua
文件:wiki_insecure/users/ArielManzur/tolua++/tolua_base.h
创建 .pkg 文件
// mypackage.pkg $#include "tolua_base.h" class Widget { protected: virtual bool input_event(Event* e); public: virtual void add_child(Widget* child); void close(); Widget(string p_name); };
生成包
tolua++ -L virtual_method_hooks.lua mypackage.pkg > mypackage.cpp (compile 'mypackage.cpp' with the rest of the code)
在您的 lua 脚本中使用 Lua__Widget 类
-- custom_widget.lua require "mypackage" local CustomWidget = {} CustomWidget.__index = CustomWidget function CustomWidget:input_event(e) if e.type = Event.KEY_PRESS and e.key_code == KEY_ESCAPE then -- close the widget when escape is pressed self:close() return true end -- call Widget::input_event return self:Widget__input_event(e) end function CustomWidget:new(name) -- create a table and make it an 'instance' of CustomWidget local t = {} setmetatable(t, CustomWidget) -- create a Lua__Widget object, and make the table inherit from it local w = Lua__Widget:new(name) tolua.setpeer(w, t) -- use 'tolua.inherit' on lua 5.0 -- 'w' will be the lua object where the virtual methods will be looked up w:tolua__set_instance(w) return w -- return 't' on lua 5.0 with tolua.inherit end
在此示例中,生成了类 'Lua__Widget'。Lua__Widget 具有 Widget 的所有构造函数,以及一个方法 'tolua__set_instance',用于提供将查找虚拟方法的 lua 对象(在本例中,我们使用与 c++ 对象相同的用户数据对象,因为我们的 lua 函数覆盖了 c++ 函数)。此对象将作为 self
传递给 lua 方法。Lua__Widget 还公开 Widget 的虚拟方法,以便直接调用。
从具有虚拟方法的类继承的子类也将生成代码以从 lua 实现这些方法,但前提是子类本身具有任何虚拟方法。例如,如果我们在 pkg 中添加以下内容
class Label : public Widget { public: void set_text(string p_text); };
这将不会生成 Lua__Label
类。为此,我们需要添加至少一个虚拟方法。请考虑以下示例
class Label : public Widget { private: virtual void add_child(Widget* child); public: void set_text(string p_text); };
在这种情况下,Lua__Label 类可用的唯一虚拟方法将是 input_event
(从 Widget 继承)。在 pkg 上将 add_child
声明为私有的原因是,如果该方法实际上是私有的,而我们在 pkg 上没有将其声明为私有,则生成的代码将尝试在 Lua__Label 上使用它,这将导致编译错误。
文件 virtual_method_hooks.lua 有 3 个可以更改的标志(位于文件开头)。
disable_virtual_hooks
:一个快速标志,用于禁用整个功能。如果将其设置为 true
,则不会为虚拟方法生成任何特殊代码。
enable_pure_virtual
:启用对纯虚拟方法的支持。如果将其设置为 false
,则输出代码在处理具有纯虚拟方法的类时将更加“保守”。不会输出任何构造函数,并且代码仅与 GCC 4(通过预处理器开关)编译,GCC 4 对纯虚拟类更加宽容。
default_private_access
:这是一个标志,用于完全启用来自 ToluappClassAccessLabels 的代码。默认情况下,tolua++ 将类的内容视为 public
,但由于我们可以拥有 private
虚拟方法,因此可以选择在 pkg 文件上默认将访问权限设置为 private
。
由于Lua不强制函数签名,查找函数的唯一方法是通过函数名。因此,当存在多个具有相同名称的C++方法时,您的Lua函数应该准备好处理所有版本的函数。
此外,当在父类中查找方法时,只使用名称来匹配它们(这是当前版本的限制)。例如,如果您将以下代码添加到示例包中
class Button : public Widget { public: virtual void add_child(Label* child); };
只有最后一个版本的add_child
将可用于类Lua__Button
。
目前只支持一层命名空间。为了避免无限递归,只有Lua函数(而不是lua_cfunctions)从虚拟方法中调用。
某些版本的tolua++(例如**1.0.92**)在使用'default_private_access'标志时存在问题。如果您的虚拟类中的方法没有被导出,请尝试将该标志设置为false
。您需要在默认情况下具有私有内容的类声明的开头添加一个private:
标签。
请将问题、错误或评论发送至 mailto:[email protected]