簡體   English   中英

用 Cython 包裝枚舉類

[英]Wrap enum class with Cython

我正在嘗試將枚舉類包裝在 c++ 頭文件中,以便在 cython 項目中使用。

例如,這怎么可能

enum class Color {red, green = 20, blue};

用 Cython 包裹。

CPP類

enum class Color {red, green = 20, blue}; 

類型定義

cdef extern from "colors.h":
  cdef cppclass Color:
    pass

顏色類型的定義

cdef extern from "colors.h" namespace "Color":
  cdef Color red
  cdef Color green
  cdef Color blue

Python 實現

cdef class PyColor:
  cdef Color thisobj
  def __cinit__(self, int val):
    self.thisobj = <Color> val

  def get_color_type(self):
    cdef c = {<int>red : "red", <int> green : "green", <int> blue : "blue"}
    return c[<int>self.thisobj]

另一種允許使用Cython 文檔中提到的PEP-435 枚舉的替代方法如下:

foo.h

namespace foo {
enum class Bar : uint32_t {
    Zero = 0,
    One = 1
};
}

foo.pxd

from libc.stdint cimport uint32_t

cdef extern from "foo.h" namespace 'foo':

    cdef enum _Bar 'foo::Bar':
        _Zero 'foo::Bar::Zero'
        _One  'foo::Bar::One'


cpdef enum Bar:
    Zero = <uint32_t> _Zero
    One  = <uint32_t> _One

主文件

from foo cimport Bar

print(Bar.Zero)
print(Bar.One)

# or iterate over elements
for value in Bar:
    print(value)

這是使用更改 cython 和 C++ 標識符名稱的功能的替代解決方案。

頭文件

namespace foo {
enum class Bar : uint32_t {
    BAZ,
    QUUX
};
}

頭文件.pxd

cdef extern from "header.hpp" namespace "foo::Bar":
    cdef enum Bar "foo::Bar":
        BAZ,
        QUUX

主文件

from header cimport *
cdef void doit(Bar b):
    pass

doit(BAZ) # Not Bar.BAZ, which would have been nicer.

它有效地告訴 cython 存在一個名為“foo::Bar”的命名空間,並在其中放置了一個 C 樣式的枚舉。 為了抵消 Bar 否則會變成 "foo::Bar::Bar" 的事實,而 "foo::Bar::Bar" 也被賦予了一個覆蓋的名稱。 這確實意味着 Bar::BAZ 在 cython 中被稱為 BAZ,而不是 Bar.BAZ,后者是枚舉類的更慣用的表示,但它似乎足夠接近。

最新的 cython (3.x) 直接支持 c++ enum class ,它記錄在這里: https ://cython.readthedocs.io/en/latest/src/userguide/wrapping_CPlusPlus.html#scoped-enumerations

下面是一個例子:

// cpp header
enum class State: int
{
    Good,
    Bad,
    Unknown,
};


const char* foo(State s){
    switch (s){
        case State::Good:
            return "Good";
        case State::Bad:
            return "Bad";
        case State::Unknown:
            return "Unknown";
    }
}

Cython 的一面

cdef extern from "test.h":
    cpdef enum class State(int):
        Good,
        Bad,
        Unknown,

    const char* foo(State s)
    
def py_foo(State s):
    return foo(s)

調用py_foo(State.Good)返回b'Good'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM