Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrap enum class with Cython

I am trying to wrap an enum class in a c++ header file for use in a cython project.

For example, how can this

enum class Color {red, green = 20, blue};

be wrapped with Cython.

like image 470
user3684792 Avatar asked Jun 23 '15 11:06

user3684792


2 Answers

Here's an alternative solution that uses the ability to change the name of cython and C++ identifiers.

header.hpp

namespace foo {
enum class Bar : uint32_t {
    BAZ,
    QUUX
};
}

header.pxd

cdef extern from "header.hpp" namespace "foo::Bar":
    cdef enum Bar "foo::Bar":
        BAZ,
        QUUX

main.pyx

from header cimport *
cdef void doit(Bar b):
    pass

doit(BAZ) # Not Bar.BAZ, which would have been nicer.

It's effectively telling cython that there exists a namespace called "foo::Bar", and puts a C-style enum in it. To counteract the fact that Bar would otherwise become "foo::Bar::Bar" that is also given an overridden name. It does mean that Bar::BAZ is referred to as BAZ in cython, rather than Bar.BAZ which would be a more idiomatic representation of enum classes, but it seems close enough.

like image 193
Rich L Avatar answered Sep 30 '22 13:09

Rich L


The latest cython (3.x) has a direct support for c++ enum class, it's documented here: https://cython.readthedocs.io/en/latest/src/userguide/wrapping_CPlusPlus.html#scoped-enumerations

Here is an example:

// cpp header
enum class State: int
{
    Good,
    Bad,
    Unknown,
};


const char* foo(State s){
    switch (s){
        case State::Good:
            return "Good";
        case State::Bad:
            return "Bad";
        case State::Unknown:
            return "Unknown";
    }
}

Cython's side

cdef extern from "test.h":
    cpdef enum class State(int):
        Good,
        Bad,
        Unknown,

    const char* foo(State s)
    
def py_foo(State s):
    return foo(s)

call py_foo(State.Good) returns b'Good'

like image 24
oz1 Avatar answered Sep 30 '22 11:09

oz1