【问题标题】:How to directly map a Lua variable to a C++ variable?如何直接将 Lua 变量映射到 C++ 变量?
【发布时间】:2011-09-11 22:32:37
【问题描述】:

我正在开发一个使用 Lua 定义 NPC 的 C++ 游戏引擎。

我可以像这样定义一个原型 NPC:

orc =
{
    name = "Generic Orc",
    health = 100
}

function orc:onIdle()
    print("Orc idles...")
end

然后使用entitySpawn(orc) 生成“Orc”实例。这是一个 C++ 函数,它从给定的表中读取诸如健康和名称之类的值,在 C++ 中使用给定的值创建一个实体对象,并为特定的 NPC 创建一个 Lua 表。

现在,我想在 Lua 中的 orc.health 变量和 C++ 中相应 Entity 对象的 mHealth 成员变量之间建立直接联系,这样我就可以在 Lua 中赋值并立即在 C++ 中使用它反之亦然。

这甚至可能吗?还是我必须使用 setter / getter 函数?我已经查看了轻量级用户数据,并开始在 Lua 中存储指向 C++ 变量的指针,但无法赋值。

【问题讨论】:

    标签: c++ variables pointers mapping lua


    【解决方案1】:

    这是可能的。我假设 entitySpawn 返回 C++ 为实体创建的表。我还将假设您可以从 C++ 公开一个函数,该函数接受一个实体的表并返回当前的运行状况,并且类似地用于设置。 (您可以使用指向 C++ 对象的轻量级 userdata 指针作为该表的成员来实现。)

    所以丑陋的方式看起来像这样:

    local myOrc = entitySpawn(orc)
    local curHealth = getEntityHealth(myOrc)
    setEntityHealth(myOrc, curHealth + 10)
    

    为了让这个更漂亮,我们可以在元表中找到一些乐趣。首先,我们将为我们关心的所有属性放置访问器。

    entityGetters = {
        health = getEntityHealth,
        -- ...
    }
    entitySetters = {
        health = setEntityHealth,
        -- ...
    }
    

    然后我们将创建一个metatable,它使用这些函数来处理属性分配。

    entityMetatable = {}
    
    function entityMetatable:__index(key)
        local getter = entityGetters[key]
        if getter then
            return getter(self)
        else
            return nil
        end
    end
    
    function entityMetable:__newindex(key, value)
        local setter = entitySetters[key]
        if setter then
            return setter(self, value)
        end
    end
    

    现在您需要让entitySpawn 分配元表。您可以使用 lua_setmetatable 函数来执行此操作。

    int entitySpawn(lua_State* L)
    {
        // ...
        // assuming that the returned table is on top of the stack
        lua_getglobal(L, "entityMetatable");
        lua_setmetatable(L, -2);
        return 1;
    }
    

    现在你可以写得很好了:

    local myOrc = entitySpawn(orc)
    myOrc.health = myOrc.health + 10
    

    请注意,这要求entitySpawn 返回的表 具有健康属性集。如果是这样,则永远不会针对该属性咨询元表。

    您可以使用 C++ 而不是 Lua 创建 entityGettersentitySettersentityMetatable 表,以及 __index__newindex 元方法,如果您觉得这样更简洁的话,但总体思路是一样的。

    【讨论】:

    • 谢谢,这正是我需要的!看来我的研究方向完全错误:)
    【解决方案2】:

    我没有时间给你任何代码,但请记住orc.healthorc["health"] 相同;也就是说,orc 是一个表,"health" 是一个元素。

    考虑到这一点,您可以更改表的indexnewindex metamethods 以拥有自己的特定行为。将您的“真实”兽人实例存储为一些私有元数据,然后使用它进行更新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 2023-01-22
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 2021-11-28
      相关资源
      最近更新 更多