使用c ++和lua的泛型类型

时间:2014-11-29 21:52:28

标签: c++ lua luabind

我有一个Entity类,其中包含一些属性(数据片段)。这些属性存储在名称=>的地图中。值。

class Entity
{
public:
    // Sets the attribute with the specified name.
    void attribute(const std::string& name, const GenericType& value) {
        m_attributes[name] = value;
    }

    // Returns the attribute with the specified name.
    GenericType& attribute(const std::string& name) {
        return m_attributes[name];
    }

    template<typename AttributeType>
    void attribute(const std::string& name, const AttributeType& value) {
        m_attributes[name] = GenericType(value);
    }

    template<typename AttributeType>
    AttributeType& attribute(const std::string& name) {
        return generic_cast<AttributeType>(m_attributes[name]);
    }

private:
    // Map of attributes from name => value.
    std::unordered_map<std::string, GenericType> m_attributes;
}

我有一个创建或覆盖属性的方法,另一个方法返回具有指定名称的属性。前两种方法暴露给Lua。最后两种方法用于从我的c ++源代码访问和修改属性。问题是属性可以是任何类型。例如,我希望能够:

entity.attribute("Health", 100)
entity.attribute("Position", Vector3(1,2,3))
entity.attribute("Position").x = 4

应该可以从我的c ++源文件和lua脚本中读取和修改属性。我以前一直在使用ChaiScript,我使用Boxed_Value类作为我的GenericType。这很好用,但过多的编译时间迫使我去寻找其他地方。

有没有办法用LuaBind(或任何其他Lua绑定库)实现这一目的? luabind::object类看起来很有希望但它的构造函数中需要一个lua_State类。这令我担心,因为我觉得Entity班级对Lua州一无所知。

1 个答案:

答案 0 :(得分:1)

在LuaBind中,您的实体类不需要了解有关lua状态的任何信息。 Lua绑定不必在语法上与C ++ API一对一,因为它们是完全不同的语言。

在你的情况下,我宁愿将api拆分为getter和setter。通过显示的Entity课程,您可能会努力让LuaBind明确地做您想做的事情。您可以做的是在C ++端为Entity编写一个包装类,它将具有符合LuaBind的简单接口,即使用明确的名称拆分getter和setter。

Blufs就是一个例子,展示了我的意思。

举个简单的例子,with LuaBridge

创建一个简单的非手动绑定有点棘手:

class Entity {
    std::map<std::string, int> attributes;

public:
    void attribute(std::string const& key,int value) {
        attributes[key] = value;
    }

    int& attribute(std::string const& key) {
        return attributes[key];
    }
};

可以绑定包装器:

class EntityWrapper {
    Entity entity;
public:
    void set_int(std::string const& key,int value) {
        entity.attribute(key,value);
    }


    int get_int(std::string const& key) {
        return entity.attribute(key);
    }
};

一个简单的绑定:

void luabridge_bind(lua_State *L) {
 luabridge::getGlobalNamespace(L)
 .beginClass<EntityWrapper>("Entity")
 .addConstructor<void(*)(), RefCountedPtr<EntityWrapper> /* creation policy */ >()
    .addFunction("get_int", &EntityWrapper::get_int)
    .addFunction("set_int", &EntityWrapper::set_int)
 .endClass()
 ; 
}

在Lua:

local e = Entity()
e:set_int("bla",42)
print(e:get_int("bla"))

如果您需要Entity与其他API进行交互,请编写获取原始包装对象的小包装器并将其传递给其他函数。