c++ - 在 Selene 中包装一个枚举以便在 Lua 中访问

标签 c++ enums lua

我正在使用 Selene包装 C++ 类和函数以便从 Lua 访问。我有一个简单的枚举类:

enum class Motion {
    UP = 0,
    DOWN = 1,
    REPEAT = 2,
};

我想将它包装在 Lua 状态中,这样我就可以在 Lua 中说出类似“Motion.DOWN”的内容并得到 1。

第一次尝试:

void register(sel::State &L) {
    L["Motion"].SetClass<Motion>();
}

编译器提示它不是一个类。

...
/source/desktop/../external/Selene/include/selene/Class.h:41:10: 
    error: creating pointer to member of non-class type 'Motion'
 void _register_member(lua_State *state,
...

第二次尝试:

void register(sel::State &L) {
    L["Motion"] = Motion;
}

这不会编译,出现关于“expecting primary expression”的错误,它不是有效的 C++。如果我尝试使用 &Motion,我会遇到同样的错误。

有没有办法做到这一点?最好不要让我再次列出所有枚举常量。

最佳答案

这在 Selene 中是不可能的。

我采用的解决方案是定义一个类 DynEnum,它在内部使用映射来跟踪标签和值。

/**
 * Simple class for enum values
 */
class DynEnum {
  public:
    DynEnum(std::map<std::string, int> tbl) : tbl(tbl) {}

    int of(std::string tag) {
        if (tbl.count(tag) > 0) {
            return tbl[tag];
        }
        throw std::runtime_error("Enum tag not found");
    }

    std::string lookup(int v) {
        for (auto &p : tbl) {
            if (p.second == v) {
                return p.first;
            }
        }
        throw std::runtime_error("Enum value not found");
    }

  private:
    std::map<std::string, int> tbl;
};

然后像这样实例化对象:

DynEnum Motion({
    {"UP", 0},
    {"DOWN", 1},
    {"REPEAT", 2},
});

然后使用 Selene 绑定(bind):

L["Motion"].SetObj(Motion,
    "of", &DynEnum::of,
    "lookup", &DynEnum::lookup);

此方法有性能开销,但在我的应用程序中这不是什么大问题。它还具有允许在 Lua 中从数字转换为字符串的优点,这有助于调试。

关于c++ - 在 Selene 中包装一个枚举以便在 Lua 中访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36185075/

相关文章:

c++ - 通过->语法c++从指针访问函数

lua - 如何从其他脚本访问本地表变量

c++ - 路亚 "attempt to index a nil value"

c++ - header 实现和用于优化的内联关键字

c++ - 带有标题的循环依赖。使用#ifndef 和#define

c++ - 检查相同的字符串文字是否存储在相同的地址

将枚举变量转换为枚举类型

c# - 无需键入其类名即可获取枚举?

ios - 在 Swift 中处理枚举的情况

lua - 延迟 Lua 函数,使其在 Neovim 成功启动后运行