diff options
author | Rob Taylor <rob.taylor@codethink.co.uk> | 2009-02-03 21:28:02 +0000 |
---|---|---|
committer | Rob Taylor <rob.taylor@codethink.co.uk> | 2009-02-03 21:28:02 +0000 |
commit | c7cb2cd35bf772c7ab8ba8ceea350aad8bd9cc8f (patch) | |
tree | b05f009bf2d319fc2b0219cba24cf9d3d42d35ea /python | |
parent | 21b7342a347dc9d7c1b44cca4c259f0e38ce11e4 (diff) |
Start of ctypes-based python bindings for libcontextprovider.
Diffstat (limited to 'python')
-rw-r--r-- | python/CTypesHelpers.py | 65 | ||||
-rw-r--r-- | python/ContextProvider.py | 40 |
2 files changed, 105 insertions, 0 deletions
diff --git a/python/CTypesHelpers.py b/python/CTypesHelpers.py new file mode 100644 index 00000000..bada4e0d --- /dev/null +++ b/python/CTypesHelpers.py @@ -0,0 +1,65 @@ +# From http://wwwx.cs.unc.edu/~gb/wp/blog/2007/02/11/ctypes-tricks/ + +from ctypes import * + +def cfunc(name, dll, result, *args): + '''build and apply a ctypes prototype complete with parameter flags''' + atypes = [] + aflags = [] + for arg in args: + atypes.append(arg[1]) + aflags.append((arg[2], arg[0]) + arg[3:]) + return CFUNCTYPE(result, *atypes)((name, dll), tuple(aflags)) + +class ListPOINTER(object): + '''Just like a POINTER but accept a list of ctype as an argument''' + def __init__(self, etype): + self.etype = etype + + def from_param(self, param): + if isinstance(param, (list,tuple)): + return (self.etype * len(param))(*param) + +class ListPOINTER2(object): + '''Just like POINTER(POINTER(ctype)) but accept a list of lists of ctype''' + def __init__(self, etype): + self.etype = etype + + def from_param(self, param): + if isinstance(param, (list,tuple)): + val = (POINTER(self.etype) * len(param))() + for i,v in enumerate(param): + if isinstance(v, (list,tuple)): + val[i] = (self.etype * len(v))(*v) + else: + raise TypeError, 'nested list or tuple required at %d' % i + return val + else: + raise TypeError, 'list or tuple required' + + +class ByRefArg(object): + '''Just like a POINTER but accept an argument and pass it byref''' + def __init__(self, atype): + self.atype = atype + + def from_param(self, param): + return byref(self.atype(param)) + +# hack the ctypes.Structure class to include printing the fields +class _Structure(Structure): + def __repr__(self): + '''Print the fields''' + res = [] + for field in self._fields_: + res.append('%s=%s' % (field[0], repr(getattr(self, field[0])))) + return self.__class__.__name__ + '(' + ','.join(res) + ')' + @classmethod + def from_param(cls, obj): + '''Magically construct from a tuple''' + if isinstance(obj, cls): + return obj + if isinstance(obj, tuple): + return cls(*obj) + raise TypeError + diff --git a/python/ContextProvider.py b/python/ContextProvider.py new file mode 100644 index 00000000..4048fc16 --- /dev/null +++ b/python/ContextProvider.py @@ -0,0 +1,40 @@ +from ctypes import * +from CTypesHelpers import * + + +class STRING_SET(c_void_p): + pass + +class CHANGE_SET(c_void_p): + pass + +class ContextProvider: + def __init__(self): + self.define_types() + self.define_functions() + + def define_types(self): + self.dll = CDLL("libcontextprovider.so") + self.STRING_ARRAY = POINTER(c_char_p) + self.GET_CALLBACK = CFUNCTYPE(STRING_SET, CHANGE_SET, c_void_p) + self.SUBSCRIBE_CALLBACK = CFUNCTYPE(STRING_SET, c_void_p) + + def define_functions(self): + self.init = cfunc('context_provider_init', self.dll, None, + ('provided_keys', ListPOINTER (c_char_p), 1), + ('useSessionBus', c_int, 1), + ('get_cb', self.GET_CALLBACK, 1), + ('get_cb_target', c_void_p, 1), + ('first_cb', self.SUBSCRIBE_CALLBACK, 1), + ('first_cb_target', c_void_p, 1), + ('last_cb', self.SUBSCRIBE_CALLBACK, 1), + ('last_cb_target', c_void_p, 1)) + self.no_of_subscribers = cfunc('context_provider_no_of_subscribers', self.dll, c_int, + ('key', c_char_p, 1)) + + self.change_set_create = ('context_provider_change_set_create', self.dll, CHANGE_SET, + None); + + +if __name__ == "__main__": + cp = ContextProvider() |