【问题标题】:Self pointer, in C++ function from Lua自指针,在 Lua 的 C++ 函数中
【发布时间】:2015-03-02 15:30:27
【问题描述】:

我对 Lua 还是很陌生,在 Lua 中注册 C 函数时,我很难找出最佳方法,但是从 C++ 类中,当涉及从对象中检索自指针时不是从 Lua 创建的。


考虑以下代码:

foo.h

class Foo
{
public:
    static int lua_DoSomething(lua_State* pState);
    void DoSomething();
};

foo.cpp

static const luaL_Reg methods[] =
{
    {"DoSomething", Foo::lua_DoSomething},
    {nullptr, nullptr}
};

extern "C"
{
    int luaopen_Foo(lua_State* pState)
    {
        luaL_register(pState, "Foo", methods);
        return 1;
    }
}

int Foo::lua_DoSomething(lua_State* pState)
{
    Foo* self = ???; //<-- how to get self pointer here?
    self->DoSomething();
    return 0;
}

void Foo::DoSomething()
{
    //...
}

script.lua

Foo.DoSomething();

所以我的函数注册得很好,Foo::lua_DoSomething 被调用(耶!)。

但是,由于 Foo 对象不是从 Lua 创建的,我将如何在函数 Foo::lua_DoSomething 中获取 self 指针?

我是否必须向 Lua 注册某种 Foo::GetInstance 函数以获取 Foo 指针,然后以某种方式在 Lua 脚本中使用它?

如果有多个Foo 实例怎么办?

对于不是从 Lua 创建的对象,最简洁的通用方法是什么?

谢谢!

【问题讨论】:

  • 你确定编译没有警告吗?无论如何,Lua 堆栈上的第一个参数将是它应该执行的对象。这可能是指您的Foo,也可能不是。
  • @Deduplicator 当然Foo* self = ???; 行不会编译,它只是为了突出我需要帮助的位置。无论如何,如果对象不是由 Lua 创建的,Lua 堆栈如何包含我的 C++ 对象的指针?
  • 您说 lua 不会创建 Foo,但您仍然需要以某种方式获取 Foo 实例。您的 lua-C 绑定 API 设置目前如何做到这一点?米兰的回答可能是最有帮助的。
  • 在你的情况下,我建议首先使用专用的包装器,例如 LuaBridge 或 LuaBind

标签: c++ pointers lua self


【解决方案1】:

你需要在lua状态中传递一些信息,这将帮助你识别“自我”。例如,您可以将 Foo 类的所有创建实例存储在 map 中,将实例与某个标识符(int id)相关联,或者只是将实例的指针传递给 size_t。 然后在 lua_DoSomething 方法中,从 lua 状态获取该信息,将其强制转换为 Foo 实例,然后您就拥有了“自我”。

帖子编辑: 从这方面我对lua不是很熟悉(我在lua中做过一些脚本)。但是...
在 lua 中,您可以存储数据,并且可以在 lua 和 C++ 之间交换这些数据。 我猜你在 lua 中有 C++ Foo 的对应部分,我们将其命名为 LFoo。
C++ 中的 Foo 有方法 DoSomething ,我猜你想在 lua 中做同样的事情(我知道你不能在 lua 中有类,但有一些方法可以用表来模仿它)。 Foo 实例有它的地址(this)。将此地址传递给 lua 并将值存储在 LFoo 的表中。当你在 lua 中调用 DoSomething 函数时,该函数将调用静态方法 lua_DoSomething,将 LFoo 表中的值通过 lua_state 传回该方法。用它来获得“这个”。

尝试使用这样的东西:

void RegisterFoo(lua_state* pState, Foo* foo)
{
    Foo** p = (Foo**)lua_newuserdata(pState,sizeof(foo));
    *p = foo;
    ...
}

int Foo::lua_DoSomething(lua_State* pState)
{
    // pass the pointer at first index for example
    Foo* self = (Foo*)lua_topointer(pState,0);
    self->DoSomething();
    return 0;
}

我找到了这些函数的解释:
http://pgl.yoyo.org/luai/i/lua_newuserdata
http://pgl.yoyo.org/luai/i/lua_topointer

【讨论】:

  • 是的,我认为可能是这样。 Lua C API 并不完全直观,我对 Lua 语言本身了解不多,仍在学习中。如果您对您的建议有任何详细的见解,我将不胜感激!谢谢!
  • 谢谢,通过一些工作,我确实得到了我想要的结果。你知道,为了存储一个指针,我发现使用lua_pushlightuserdata 效果最好,因为它确实把它放在了堆上。
【解决方案2】:

在 Foo 类型的成员函数中,会自动为您提供“this”指针。它的类型是 const Foo*。通常不需要,因为在大多数情况下,您可以直接使用该成员。例如:您可以替换:

int Foo::lua_DoSomething(lua_State* pState)
{
  this->DoSomething();
  return 0;
}

int Foo::lua_DoSomething(lua_State* pState)
{
    DoSomething();
    return 0;
}

【讨论】:

  • 非静态成员引用必须是相对于特定对象的,所以这不起作用。
  • 我想我错过了这个问题的 lua 特异性,并假设他指的是这个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
  • 2016-06-23
  • 2010-11-19
  • 2021-10-30
相关资源
最近更新 更多