我想在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.GOOD
,c_library.BAD
,
和c_library.Status
,其行为类似于enum。然而
调用函数hello
的返回值返回纯整数:
>>> c_library.hello()
0
>>> type(c_library.hello())
<class 'int'>
我也希望将结果包装在相同类型的枚举中。 我可以更改cython文件,但不能更改基础的C代码。有可能吗?
答案 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'>
可能值得注意的事情:
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
功能,因此不会造成混乱。