在cython中包装一个typedef枚举 [英] Wrapping a typedefed enum in cython
问题描述
我想在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 $ c $中编写了以下cython代码c>:
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 $的原因c $ c>函数,因此不会造成混乱。
- 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 preferSTATUS
- it is up to you). See the wording in C11-standard on different name spaces here or this great answer (even if it is aboutstruct
). 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
ascdef
-function I would probably usec_hello
to avoid overhead of creating an enum - that is the reasonhello()
is defined as adef
-function, so there is no confusion.
这篇关于在cython中包装一个typedef枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!