DRz
DRz

Reputation: 1156

Fetching a C variable value in an enum using its name (a Python string) in Python

Basically, I am wrapping a C API in Python (using CFFI (which is awesome)).

I have an enum in that C API:

typedef enum
{
    enum1 = value1;
    enum2 = value2;
    ...
} enumSomething;

In Python, I receive the name of a variable which is in that enumeration, as a string : "enum1". I would like to get value1.

Using CFFI, you can wrap an enum and access its members easily (here is an example). My problem here is that I have strings that represent the name of the variable, not the variable itself.

Thus, cwrapper.c."enum1" would not work (cwrapper being the name of the module that wraps and c the name returned by ffi.dlopen(libname) while wrapping the library).

I could make a dictionary that would map the variable name as a string to the real variable, such as:

enum = { "enum1" : cwrapper.c.enum1, "enum2" : cwrapper.c.enum2, ... } 

But at this point, I would better rewrite the enum as a Python dictionary.

I know I could also use a regex to read the C file, but I think there is still a better way for handling that, that I haven't thought of. Any idea?

Upvotes: 1

Views: 641

Answers (2)

Ethan Furman
Ethan Furman

Reputation: 69051

Building on Antti's answer, a proper Python Enum could be built:

Strategy = enum.Enum('Strategy', ffi.typeof('strategy').relements)

list(Strategy)
# [<Strategy.RANDOM: 0>, <Strategy.IMMEDIATE: 1>, <Strategy.SEARCH: 2>]

Upvotes: 2

cwrapper.c."enum1" is not valid syntax in Python in general. You need to use getattr:

>>> getattr(cwrapper.c, "enum1")
42

However a cleaner approach is to get the actual type using typeof; then get its relements, which is a dictionary!

>>> import cffi
>>> ffi = cffi.FFI()
>>> ffi.cdef('typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;')
>>> typeof_strategy = ffi.typeof('strategy')
>>> typeof_strategy.relements
{'RANDOM': 0, 'SEARCH': 2, 'IMMEDIATE': 1}
>>> typeof_strategy.relements['SEARCH']
2

Upvotes: 3

Related Questions