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.
ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.
ctypes allows to create C callable function pointers from Python callables. These are sometimes called callback functions. First, you must create a class for the callback function, the class knows the calling convention, the return type, and the number and types of arguments this function will receive.
An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With