wlav / cppyy

Other
400 stars 41 forks source link

C-style anonymous enums are of type `int` instead of the real enum #64

Open b-macdonald opened 2 years ago

b-macdonald commented 2 years ago

I'm running into an issue where C-style anonymous enums, like in the code snippet below, are considered to be objects of class int, rather than real enums.

typedef enum
{
    OFF,
    ON
} Status_E;
>>> print(cppyy.gbl.Status_E)
<class 'int'>

If I make them non-anonymous, like the next snippet, then I can access the Status_E enum in cppyy as a real type:

typedef enum Status_E
{
    OFF,
    ON
} Status_E;
>>> print(cppyy.gbl.Status_E)
<class '__main__.Status_E'>

This is important for a project of mine where we do something similar to the following (smallest MRE I could make 😄):

import cppyy

cppyy.cppdef("""\
typedef enum
{
    OFF,
    ON
} Status_E;

template <class E>
class TemplatedClass {
  public:
    TemplatedClass(E e)
        : _enum(e) {};

    E _enum;
};

void print_function(TemplatedClass<Status_E> c)
{
    std::cout << "Enum: " << c._enum << std::endl;
}
""")

import cppyy.gbl as g

obj = g.TemplatedClass[g.Status_E](g.ON)
g.print_function(obj)

By default, this will lead to a traceback:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: void ::func(TemplatizedClass<Status_E> c) =>
    TypeError: could not convert argument 1

This is because g.Status_E is an integer, so the overload fails (print_function(TemplatedClass<int>) doesn't exist). If you use typedef enum Status_E instead of typedef enum, it will work fine.

Sadly, my codebase is too large and divided between too many teams to make a replacing all instances of typedef enum with the more verbose form viable. Is there an alternate solution, or would it be possible to make cppyy point to the right class type to begin with?

Thanks!

wlav commented 2 years ago

Problem even runs a bit deeper ... The obvious thing to do would be obj = g.TemplatedClass["Status_E"](g.ON) (note the use of "), but that fails in the generation of the wrapper function.

I love enums. :}

b-macdonald commented 1 year ago

I see there was a commit added to the 3.0.0 release here with the message "test for unnamed but typedef'ed enums"

Is that related to this issue? Just made a conda env & installed 3.0.0, but the above MRE still considers Status_E to be an int

Happy to dig into this issue if you have any tips on where to start (i.e. cppyy-cling, cppyy-backend, copy...)

mattparks commented 1 month ago

@wlav Has this issue been resolved in recent Cppyy releases?

wlav commented 1 month ago

No, it doesn't look like it: it still fails.