问题描述
我正在使用 pybind11 为我的 C++ 库提供 Python 接口。 我的库包含枚举,我为它们提供了方便的函数,以允许遍历枚举值并转换为字符串; 举个例子
template <typename Enum>
struct iter_enum
{
struct iterator
{
using value_type = Enum;
using difference_type = ptrdiff_t;
using reference = const Enum&;
using pointer = const Enum*;
using iterator_category = std::input_iterator_tag;
iterator(Enum value) : cur(value) {}
reference operator * () { return cur; }
pointer operator -> () { return &cur; }
bool operator == (const iterator& other) { return cur == other.cur; }
bool operator != (const iterator&other) { return!(*this == other); }
iterator& operator ++ () { if (cur != Enum::Unknown) cur = static_cast<Enum>(static_cast<std::underlying_type_t<Enum>>(cur) + 1); return *this; }
iterator operator ++ (int) { iterator other = *this; ++(*this); return other; }
private:
Enum cur;
};
iterator begin()
{
return iterator(static_cast<Enum>(0));
}
iterator end()
{
return iterator(Enum::Unknown);
}
};
enum class Colour : char
{
Black = 0,
Blue,
Red,
Yellow,
Unknown
};
const char* to_string(Colour colour)
{
switch (colour) {
case Colour::Black: return "Black";
case Colour::Blue: return "Blue";
case Colour::Red: return "Red";
case Colour::Yellow: return "Yellow";
default: return "Unknown";
}
}
int main()
{
for (auto colour : iter_enum<Colour>())
std::cout << to_string(colour) << '\n';
}
使用 pybind11 移植此类代码时,我目前将迭代器定义为静态成员函数,
pybind11::enum_<Colour>(m, "Colour")
.value("Black", Colour::Black)
// add other values and __str__
.def_static("iter", []() {
iter_enum<Colour> i;
return pybind11::make_iterator(i.begin(), i.end();
});
但是我希望能够在 Python 方面写一些类似的东西
for c in Colour:
print("Colour")
就像我对使用 Python 的enum.Enum
定义的枚举enum.Enum
。
我知道我可以使用元类Python中实现这一点,但我不能从pybind11文档,我能找到工作的元类了和例子(线334)如何写在C ++结束这样的元类。
据我所知,元类必须使用 C API PyObject
类型公开。
任何关于我是否在正确的轨道上的信息,如果是的话,如何编写这样一个使用我的iter_enum
类的元类,将不胜感激。
1楼
您也许可以使用如下所示的内容迭代 pybind11 公开的 C++ 枚举。
for name, enum_value in Color.__members__.items():
print(name, enum_value)
我发现这种方法可行的方法是运行dir(EnumClass)
并查看所有可用的私有属性,其中__members__
就是其中之一。