在cython中包装一个typedef枚举 [英] Wrapping a typedefed enum in cython

查看:146
本文介绍了在cython中包装一个typedef枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to wrap the following code in 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

cdef extern from "library.h":

  cpdef enum Status:
    GOOD,
    BAD

  ctypedef Status STATUS

  cpdef STATUS hello()

模块 c_library 现在包含 c_library.GOOD c_library.BAD
c_library.Status ,其行为类似于枚举。但是,调用函数 hello
返回值返回一个简单的整数:

The module c_library now contains c_library.GOOD, c_library.BAD, and c_library.Status, which behaves like an enum. However, the return value of a call to function hello returns a plain int:

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

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

I would like the result to be wrapped in an enum of the same type as well. I can change the cython file, but not the underlying C code. Is that possible?

推荐答案

看起来像Cython的打ic(小错误?),它决定使用 __ Pyx_PyInt_From_enum __ 出于某些原因将 cdef 函数包装到 def 函数中。

That looks like a hiccup (minor bug?) of Cython, which decides to use __Pyx_PyInt_From_enum__ for some reasons when wrapping cdef-function into a def function.

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

As a quick workaround I can propose to explicitly create a Status-enum:

%%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; 将枚举的类型名称从枚举的名称空间中拉入普通变量的名称空间是一种常见的做法(但是显然这是一种品味问题,因此,如果您更喜欢 STATUS -由您决定)。请参见此处中的C11标准中的措辞。 >或此绝佳答案(即使它与 struct 有关) 。

  • cname -trick(即 Status c_hello hello() ),以便能够添加一个间接级别并保持模块的公共接口完整(即 cpdef hello())。

  • 但是,当使用 hello 作为 cdef 函数时,我可能会使用 c_hello 以避免创建枚举的开销-这就是 hello()被定义为 def 函数,因此不会造成混乱。

  • verbatim C-code is used, to make the example self-contained.
  • Using typedef enum X {...} X; to pull enum's type-name from enum's name space into the name space of ordinary variables is a common practice (but obviously this is a matter of taste, so if you prefer STATUS - it is up to you). See the wording in C11-standard on different name spaces here or this great answer (even if it is about struct).
  • cname-trick (i.e. Status c_hello "hello"()) is used, to be able to add a level of indirection and to keep the public interface of the module intact (i.e. cpdef hello()).
  • However, when using hello as cdef-function I would probably use c_hello to avoid overhead of creating an enum - that is the reason hello() is defined as a def-function, so there is no confusion.

这篇关于在cython中包装一个typedef枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆