覆盖lua中的c ++方法并在c ++中调用它

Rad*_*adi 7 c++ methods lua overriding class

我曾经认为我可以在lua中覆盖一个类方法,这样当我在C++中调用该函数时,它将执行在lua中重写的内容.我的意思是,像这样:

C++类


class Person {
public:
  Person(); // ctr
  virtual void shout(); // Meant to be overriden
};
Run Code Online (Sandbox Code Playgroud)

假设我将该类绑定到lua,以便在lua中,我可以使用该对象:


--Lua code
p = Person:new()
p:shout()
Run Code Online (Sandbox Code Playgroud)

我想要实现的是这样的:

Lua文件


--luafile.lua
p = Person:new() --instantiate

--override shout()
p.shout = function(self) print("OVERRIDEN!") end
Run Code Online (Sandbox Code Playgroud)

C++代码


int main() {
  lua_State* l = lua_open();
  luaL_loadlibs(l);
  bind_person_class(l);

  luaL_dofile("luafile.lua");
  Person* p = (Person*) get_userdata_in_global(l, "p"); // get the created person in lua
  p->shout(); // expecting "OVERRIDEN" to be printed on screen

  lua_close(l);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,您可以看到我正在尝试覆盖lua中的Person方法,并期望从c ++调用overriden方法.但是,当我尝试它时,不执行overriden方法.我想要实现的是覆盖方法在C++中执行.你是如何实现这一目标的?

===================

我已经想到了实现这个目标的方法,但我不确定这是不是很好.我的想法是导出的类应该有一个字符串,表示lua中用于保存此类实例的全局变量名.像这样:


class Person {
public:
  Person();
  string luaVarName; // lua's global variable to hold this class
  virtual void shout() { 
    luaL_dostring(luaVarName + ":shoutScript()"); // now shout will call shoutScript() in lua
  }
};
Run Code Online (Sandbox Code Playgroud)

因此,在lua中,对象负责实现shoutScript()并将全局var分配给对象:


--LUA
p = Person:new()
p.shoutScript = function(self) print("OVERRIDEN") end
p.luaVarName = "p"
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,我可以实现我想要的(尽管没有测试过).但是,有没有其他正确的方法来实现我想要的?

Mic*_*man 4

我们在lqt(Qt 到 Lua 的自动绑定)中所做的是,对于我们绑定的每个具有虚拟方法的类,我们创建一个代理“shell”类,它将自身注册到 Lua 状态。

所以对于你的(简化的)课程:

class Person {
public:
  virtual void shout(); // Meant to be overriden
};
Run Code Online (Sandbox Code Playgroud)

我们生成以下类:

class lqt_shell_Person : public Person {
  lua_State *L;
public:
  lqt_shell_Person(lua_State *L); // registers itself into the Lua state
  virtual void shout();
};
Run Code Online (Sandbox Code Playgroud)

我们使用用户数据在 Lua 中表示这些对象。__newindex每个都有自己的环境表,我们将元方法指向该表__index__index函数在环境中查找,然后在类表中查找)。使用它,用户可以在对象上存储自定义字段。他还可以实现虚函数,如下所示:

p = Person.new()
function p:shout() print("Hello world!") end
Run Code Online (Sandbox Code Playgroud)

在我们的lqt_shell_Person::shout方法中,我们首先获取参数,然后检查shout用户数据的环境表中是否存在函数。如果有,我们用参数来调用它。如果没有,我们调用原始函数。如果是抽象方法,我们会抛出一个 Lua 错误。

希望你觉得这个有用。