在cython中包装一个typedef枚举

时间:2019-01-04 22:39:34

标签: enums cython

我想在cython中包装以下代码:

enum Status {GOOD, BAD};

typedef enum Status STATUS;
// note that the typedef means people dont
// have to write `enum Status` everywhere

// just returns `GOOD`
STATUS hello();

我在c_library.pxd中编写了以下cython代码:

cdef extern from "library.h":

  cpdef enum Status:
    GOOD,
    BAD

  ctypedef Status STATUS

  cpdef STATUS hello()

模块c_library现在包含c_library.GOODc_library.BAD, 和c_library.Status,其行为类似于enum。然而 调用函数hello的返回值返回纯整数:

>>> c_library.hello()
0
>>> type(c_library.hello())
<class 'int'>

我也希望将结果包装在相同类型的枚举中。 我可以更改cython文件,但不能更改基础的C代码。有可能吗?

1 个答案:

答案 0 :(得分:1)

这看起来像是Cython的打((小错误?),出于某些原因,在将__Pyx_PyInt_From_enum__函数包装到cdef函数中时,出于某些原因决定使用def

作为一种快速的解决方法,我可以建议明确创建一个Status枚举:

%%cython
cdef extern from *:
    """
    typedef enum Status {GOOD, BAD} Status;

    // just returns `GOOD`
    Status hello() {return GOOD;}
    """
    cpdef enum Status:
        GOOD,
        BAD

    Status c_hello "hello"()

def hello():
    return Status(c_hello())

现在:

>>> type(hello())
<enum 'Status'>

可能值得注意的事情:

  • verbatim C-code用于使示例独立。
  • 使用typedef enum X {...} X;将enum的类型名称从enum的名称空间中拉到普通变量的名称空间中是一种常见的做法(但是显然这是一种品味问题,因此,如果您更喜欢STATUS-它是由你决定)。请参阅C11标准中不同名称空间here或此great answer上的措词(即使它与struct有关)。
  • cname技巧(即Status c_hello "hello"())用于添加间接级别并保持模块的公共接口完整(即cpdef hello())。 / li>
  • 但是,将hello用作cdef函数时,我可能会使用c_hello来避免创建枚举的开销-这就是hello()被定义为def功能,因此不会造成混乱。