Reputation: 25443
I have an API I'd like to use from python. That API contains flags and enums implemented with #define.
// it's just almost C so don't bother adding the typedef and parenthesis diarrhea here.
routine(API_SOMETHING | API_OTHERTHING)
stuff = getflags()
? stuff & API_SOMETHING
action(API_INTERESTING)
mode = getaction()
? mode == INTERESTING
If ignoring everything else except enums and flags now, my bindings should translate this to:
routine(["something", "otherthing"])
stuff = getflags()
if 'something' in stuff
action('interesting')
mode = getaction()
if mode == 'interesting'
Does ctypes provide mechanisms to do this straight out? If not then just tell about your 'usual' tool for handling flags and enums in python bindings.
Upvotes: 5
Views: 5373
Reputation: 25443
I'm a bit disappointed to answer to this question myself. Especially since I found it all from the f* manual.
http://docs.python.org/library/ctypes.html#calling-functions-with-your-own-custom-data-types
To complete my answer, I'll write some code that does wrap an item.
from ctypes import CDLL, c_uint, c_char_p
class Flag(object):
flags = [(0x1, 'fun'), (0x2, 'toy')]
@classmethod
def from_param(cls, data):
return c_uint(encode_flags(self.flags, data))
libc = CDLL('libc.so.6')
printf = libc.printf
printf.argtypes = [c_char_p, Flag]
printf("hello %d\n", ["fun", "toy"])
encode_flags transforms that nifty list into an integer.
Upvotes: 3
Reputation: 5538
Why don't you use c_uint
for the enum
parameter and then use a mapping like this (enums are usually unsigned integer values):
in C:
typedef enum {
MY_VAR = 1,
MY_OTHERVAR = 2
} my_enum_t;
and in Python:
class MyEnum():
__slots__ = ('MY_VAR', 'MY_OTHERVAR')
MY_VAR = 1
MY_OTHERVAR = 2
myfunc.argtypes = [c_uint, ...]
You can then pass MyEnum
fields to the function.
If you want a string representation for the enumerated values, you can use a dictionary
in the MyEnum
class.
Upvotes: 3