【问题标题】:pybind11 emulate python Enum behaviourpybind11 模拟 python 枚举行为
【发布时间】:2018-09-22 18:13:55
【问题描述】:

我正在使用 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 定义的枚举一样。我知道我可以使用元类在 Python 中实现这一点,但我无法从我可以在元类here 和示例on github(第 334 行)上找到的 pybind11 文档中解决如何在 C++ 上编写这样的元类结尾。据我所知,元类似乎必须使用 C API PyObject 类型公开。

任何关于我是否在正确的轨道上的信息,如果是这样,如何编写这样一个使用我的 iter_enum 类的元类,将不胜感激。

【问题讨论】:

    标签: python c++ enums pybind11


    【解决方案1】:

    您也许可以使用如下所示的内容遍历 pybind11 公开的 C++ 枚举。

    for name, enum_value in Color.__members__.items():
        print(name, enum_value)
    

    我发现这种方法可行的方法是运行 dir(EnumClass) 并查看所有可用的私有属性,__members__ 就是其中之一。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多