Cython: Compile error: using cpdef enum and typedef enum

Created on 18 Nov 2016  路  4Comments  路  Source: cython/cython

I observed a compilation error from clang-800.0.38 on a MacBook when using a c enum and a Cython cpdef enum. I could reproduce the issue using gcc version 4.9.2 (Raspbian 4.9.2-10). In both cases, Cython version 0.25.1 was used.

The code I ran was:

#lib.h
typedef enum { A, B, C, D} foo;
#lib.pyx
cdef extern from "./lib.h":
    cpdef enum foo:
        A, B, C, D

def t1():
    for e in foo: print(e.name)

When trying to compile, clang throws a lot of errors which all seem to correlate with the "enum foo".
A solution is to declare the enum in the .h file as following typedef enum foo { A, B, C, D} foo;or as typedef enum foo { A, B, C, D};. When changed, the code is compiled and linked to a .so file and is working as intended.

Is this intended behaviour or bug?

Most helpful comment

+1 for some kind of "cptypedef". Kinda ugly but I don't see a better way...

All 4 comments

@adippel I observed the same issue with Cython 0.25.2. Using the foo example above, the errors that were generated looked as follows:

lib.hpp:XXX: note: foo has a previous declaration here

when I changed the typedef enum {A, B, C, D} foo; to typedef enum foo {A, B, C, D} foo; the error went away. Is this intended behavior?

@robertwb is this a simple fix considering the work done on issue #531 ?

That is because cpdef enum is a variant of cdef enum which declares a non-typedef'd enum. If you declare a typedef'ed enum as a "plain" enum or vice versa it'll generate the wrong code. There's no typedef variant of cpdef enums (would that be cptypedef)?

http://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#styles-of-struct-union-and-enum-declaration

Is cptypedef something that we can add?

My current workaround is rather verbose, especially when there are a lot of enums values. It looks something like this:

cdef extern from './lib.h':
    ctypedef enum _foo 'foo':
        _A 'A'
        _B 'B'
        _C 'C'
        _D 'D'

cpdef enum foo:
    A = _A
    B = _B
    C = _C
    D = _D

My actual code is even more verbose because I prefix the ctypedef enum names so they don't pollute the global namespace.

+1 for some kind of "cptypedef". Kinda ugly but I don't see a better way...

Was this page helpful?
0 / 5 - 0 ratings