C++ enum class used in typedef causes build failure

381 views
Skip to first unread message

Sam Partington

unread,
Dec 7, 2021, 9:12:15 AM12/7/21
to cython...@googlegroups.com
Hi there,

I’m trying to use C++ enum classes with a library that we dynamically load. Because I dynamically load the library I typedef all the function pointers, and then cast the result of dlsym using that type.

Unfortunately this seems to break the fix in https://github.com/cython/cython/pull/3782 because the typedefs reference __PYX_ENUM_CLASS_DECL before it is defined.  The typedef ends up in enums.cpp on line 1065:

typedef int (*__pyx_t_5enums_pFunction)(__PYX_ENUM_CLASS_DECL E);

But __PYX_ENUM_CLASS_DECL is not defined until line 1659:

/* EnumClassDecl.proto */
#if defined (_MSC_VER)
  #if PY_VERSION_HEX >= 0x03040000 && PY_VERSION_HEX < 0x03050000
    #define __PYX_ENUM_CLASS_DECL
  #else
    #define __PYX_ENUM_CLASS_DECL enum
  #endif
#else
  #define __PYX_ENUM_CLASS_DECL enum
#endif

enums.pyx a SSCCE, built using `cythonize enums.pyx -I` is below, and results in this error:

x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I../.venv-build/include -I/usr/include/python3.6m -c .../enums.cpp -o .../enums.o
.../enums.cpp:1065:41: error: typedef ‘__pyx_t_5enums_pFunction’ is initialized (use decltype instead)
 typedef int (*__pyx_t_5enums_pFunction)(__PYX_ENUM_CLASS_DECL E);
                                         ^~~~~~~~~~~~~~~~~~~~~
.../enums.cpp:1065:41: error: ‘__PYX_ENUM_CLASS_DECL’ was not declared in this scope

If anyone has a suggestion for a workaround it would be very much appreciated. I tried moving the ctypedef into the function that initialises the symbol but cython didn’t like it there, likewise avoiding the typedef and just using the actual type in place.

Sam

# distutils: language = c++
# cython: language_level=3

cdef extern from *:
    cpdef enum class E(int):
        a = 0
        b = 1
 
ctypedef int (*pFunction)(E) nogil

cdef extern from *:
    ctypedef char const_char "const char"

cdef extern from 'dlfcn.h' nogil:
    void *dlopen(const_char *filename, int flag)
    void *dlsym(void *handle, const_char *symbol)
    unsigned int RTLD_LAZY

cdef int function(E e):
    cdef void* handle = dlopen('libsomelib.so', RTLD_LAZY)
    cdef pFunction Function = <pFunction>dlsym(handle, "Function")
    return Function(e)

Sam Partington

unread,
Dec 7, 2021, 9:34:21 AM12/7/21
to cython...@googlegroups.com
Sorry I just discovered an easy enough work around, 

cdef extern from "enum_workaround.h":
    pass

Before the typedef, which contains the EnumClassDecl.proto code.

Still, I suspect cython needs fixing to emit this earlier in the output.

Sam

Sam Partington

unread,
Dec 14, 2021, 5:45:39 AM12/14/21
to cython-users
> TLDR..... __PYX_ENUM_CLASS_DECL emitted too late for typedefs using a scoped enum

If someone could please confirm that I'm right  I can look at fixing this. It seems like a nice entry point to begin developing python.
(and perhaps point me in the right direction if you have any ideas :-) )

Thanks

Sam

da-woods

unread,
Dec 14, 2021, 2:49:09 PM12/14/21
to cython...@googlegroups.com
Looks like you put this as the start of the utility code section

//@proto_block: utility_code_proto_before_types

On 14/12/2021 19:06, da-woods wrote:
Hi Sam,

I think your analysis is broadly right. I think what you need is to make the relevant utility code appear in the section 'utility_code_proto_before_types' https://github.com/cython/cython/blob/fa8db66368a9527c8df441a0bbfee714eb795930/Cython/Compiler/Code.py#L1121.

I don't immediately know how to do that (but I'm sure it's possible!)

I'm sure a PR to do that would be welcome.

David

--

---
You received this message because you are subscribed to the Google Groups "cython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cython-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cython-users/c3a8eab9-2e6a-4ee9-9575-e7a6d7fb9e6fn%40googlegroups.com.



da-woods

unread,
Dec 14, 2021, 3:01:49 PM12/14/21
to cython...@googlegroups.com
Hi Sam,

I think your analysis is broadly right. I think what you need is to make the relevant utility code appear in the section 'utility_code_proto_before_types' https://github.com/cython/cython/blob/fa8db66368a9527c8df441a0bbfee714eb795930/Cython/Compiler/Code.py#L1121.

I don't immediately know how to do that (but I'm sure it's possible!)

I'm sure a PR to do that would be welcome.

David


On 14/12/2021 09:04, Sam Partington wrote:
Reply all
Reply to author
Forward
0 new messages