4

Say you have a C++ enum class defined like this:

/** my_enum.h **/
#include <iostream>

enum class fruit_t : unsigned char{
  none = 0x0,
  apple = 0x1,
  banana = 0x2
};

void like_fruit(fruit_t f){std::cout << "I prefer fruit number "<< f << std::endl;}

IDEAL WORLD Now, using the most recent Cython approach, you can define a nice cpdef wrapper for the C++ enum class to get a PEP 435-style Python wrapper (standard cythonize and compilation with C++ is used to run this):

# my_cython_wrap.pyx
cdef extern from "my_enum.h":
    cpdef enum class fruit_t(unsigned char):
        none = 0x0
        apple = 0x1
        banana = 0x2
    void like_fruit(fruit_t f)

def py_like_fruit(fruit_t f):
    like_fruit(f)

This way, you get an automatically translated python fruit_t type that can be passed as-is to wrapped functions requiring arguments of C++ type fruit_t. Basically awesome.

#> python
my_apple = fruit_t['apple']
py_like_fruit(my_apple)

PROBLEM This only works if the cdef extern block is defined in a .pyx file. If, on the contrary, we define it in a separate .pxd file, we no longer get the nice wrapper. In consequence, the example below fails to compile due to non-existing "fruit_t" type in pythonland:

# my_enum.pxd
cdef extern from "my_enum.h":
    cpdef enum class fruit_t(unsigned char):
        none = 0x0
        apple = 0x1
        banana = 0x2
    void like_fruit(fruit_t f)
# my_cython_wrap.pyx
from my_enum cimport *
def py_like_fruit(fruit_t f):
    like_fruit(f)

WORKAROUND We can define a different python class to act as "wrapper":

# my_cython_wrap.pyx
from my_enum cimport *
from enum import Enum
class py_fruit_t(Enum):
   none=0x0
   apple=0x1
   banana=0x2

def py_like_fruit(py_fruit_t f):
    like_fruit(f.value)

So... is there anyway to avoid this duplicated definition (the fruit_t and the py_fruit_t)?

ibarrond
  • 6,617
  • 4
  • 26
  • 45
  • 1
    This sounds like it should be a bug report more than a stack overflow question – DavidW Sep 20 '21 at 12:53
  • 1
    I would say a bug report *and* an SO question -- others may need a workaround until the issue is fixed. – Ethan Furman Sep 20 '21 at 18:13
  • @ibarrond: Can you avoid the problem by creating the Enum from the C++ source files ([documented here](https://stackoverflow.com/a/66037988/208880)) ? – Ethan Furman Sep 22 '21 at 18:32
  • @EthanFurman You're proposing to manually scan the C++ file, extract the enum from there and create an equivalent Python class. I guess it is worth trying out, but the apartent complexity of it makes me shiver. – ibarrond Sep 22 '21 at 19:29
  • @ibarrond: Well, if by "manually" you mean have the code do it -- then yes. :-) – Ethan Furman Sep 22 '21 at 20:27

0 Answers0