使用 Toluapp 实现虚拟方法

lua-users home
wiki

此 tolua++ 附加组件可用于生成代码,以允许从 lua 实现 c++ 虚拟方法。此代码是 lua_qt 中使用的代码的修改版本,与 ToluappClassAccessLabels 结合使用以实现访问标签。请注意,这不是补丁;它可以与未修改的 tolua++ 二进制文件(版本 1.0.7 或更高版本)一起使用。

需要 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 个可以更改的标志(位于文件开头)。

重载

由于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]


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于2009年1月20日下午7:38 GMT (差异)