2016-03-23 40 views
1

我使用Selene將C++類和函數包裝爲可從Lua訪問。我有一個簡單枚舉類:將枚舉包裝在Selene中以便在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; 
} 

這並不編譯,得到有關 「預計主要表達」 的錯誤,這不是有效的C++。如果我嘗試使用&Motion,我會得到相同的錯誤。

有沒有辦法做到這一點?最好不包括我再列出所有的枚舉常量。

回答

0

這是在塞勒涅不可能的。

我採用的解決方案是定義一個類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}, 
}); 

然後綁定使用塞勒涅:

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

這種方法具有性能開銷,但在我的應用程序這不是什麼大不了的事。它還具有在Lua中允許從數字轉換爲字符串的優勢,這有助於調試。