[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2 of 4] xl: support array types in IDL
tools/libxl/gentypes.py | 30 +++++++- tools/libxl/libxltypes.py | 6 + tools/python/genwrap.py | 147 ++++++++++++++++++++++++++++++++----- tools/python/xen/lowlevel/xl/xl.c | 19 ++++ 4 files changed, 178 insertions(+), 24 deletions(-) # HG changeset patch # User Gianni Tedesco <gianni.tedesco@xxxxxxxxxx> # Date 1294841273 0 # Node ID f630610c99f076ce3ceee52d888b516e70ef569a # Parent 787e699871a3d052b0f30bee4ec1dc555c0c3540 xl: support array types in IDL This is required to auto-generate language bindings for libxl_domain_config. An Array() types is implemented which causes the IDL header generator to output a pointer and a count variable for each instance. C destructor functions are also correctly generated. They python wrapper part of this patch builds on the 'shadow' references introduced in the previous patch 'pyxl: Recursively scan type-tree to produce complete binding boilerplate' This means that array fields remain as python lists and present with the expected 'by-reference' semantics. The C array is built during the 'unshadow' process before the wrapped structure is passed accross the C API boundary in to libxl. Signed-off-by: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx> diff -r 787e699871a3 -r f630610c99f0 tools/libxl/gentypes.py --- a/tools/libxl/gentypes.py Wed Jan 12 14:07:52 2011 +0000 +++ b/tools/libxl/gentypes.py Wed Jan 12 14:07:53 2011 +0000 @@ -32,6 +32,16 @@ def libxl_C_instance_of(ty, instancename else: return libxl_C_type_of(ty) + " " + instancename +def flatten_arrays(ty): + ret = [] + for f in ty.fields: + if isinstance(f.type, libxltypes.Array): + ret.append(libxltypes.Field(libxltypes.integer, "num_%s"%f.name)) + ret.append(libxltypes.Field(libxltypes.Reference(f.type.array_type), f.name)) + else: + ret.append(f) + return ret + def libxl_C_type_define(ty, indent = ""): s = "" if isinstance(ty, libxltypes.Aggregate): @@ -43,7 +53,7 @@ def libxl_C_type_define(ty, indent = "") else: s += "typedef %s {\n" % ty.kind - for f in ty.fields: + for f in flatten_arrays(ty): if f.comment is not None: s += format_comment(4, f.comment) x = libxl_C_instance_of(f.type, f.name) @@ -59,6 +69,15 @@ def libxl_C_type_define(ty, indent = "") raise NotImplementedError("%s" % type(ty)) return s.replace("\n", "\n%s" % indent) +def contains_array_dtor(ty, parent = None): + if isinstance(ty, libxltypes.Struct) and (parent is None or ty.destructor_fn is None): + for f in [f for f in ty.fields if not f.const]: + if isinstance(f.type, libxltypes.Array) and f.type.array_type.destructor_fn: + return True + if contains_array_dtor(f.type, True): + return True + return False + def libxl_C_type_destroy(ty, v, reference, indent = " ", parent = None): if reference: deref = v + "->" @@ -85,6 +104,13 @@ def libxl_C_type_destroy(ty, v, referenc s += "%s(%s);\n" % (ty.destructor_fn, makeref + v) elif isinstance(ty, libxltypes.Struct) and (parent is None or ty.destructor_fn is None): for f in [f for f in ty.fields if not f.const]: + if isinstance(f.type, libxltypes.Array): + at = f.type.array_type + if at.destructor_fn: + s += "for(i = 0; i < %s; i++)\n"%(deref + "num_" + f.name) + s += "%s%s(&%s%s[i]);\n"%(indent, at.destructor_fn, deref, f.name) + s += "free(%s%s);\n"%(deref, f.name) + continue if f.name is None: # Anonynous struct s += libxl_C_type_destroy(f.type, deref, False, "", deref) @@ -158,6 +184,8 @@ if __name__ == '__main__': for ty in [t for t in types if t.destructor_fn is not None and t.autogenerate_destructor]: f.write("void %s(%s *p)\n" % (ty.destructor_fn, ty.typename)) f.write("{\n") + if contains_array_dtor(ty): + f.write(" int i;\n") f.write(libxl_C_type_destroy(ty, "p", True)) f.write(" memset(p, LIBXL_DTOR_POISON, sizeof(*p));\n") f.write("}\n") diff -r 787e699871a3 -r f630610c99f0 tools/libxl/libxltypes.py --- a/tools/libxl/libxltypes.py Wed Jan 12 14:07:52 2011 +0000 +++ b/tools/libxl/libxltypes.py Wed Jan 12 14:07:53 2011 +0000 @@ -69,6 +69,12 @@ class Field(object): self.comment = kwargs.setdefault('comment', None) self.keyvar_expr = kwargs.setdefault('keyvar_expr', None) +class Array(Type): + """A counted array of elements""" + def __init__(self, type): + Type.__init__(self, None) + self.array_type = type + class Aggregate(Type): """A type containing a collection of other types""" def __init__(self, kind, typename, fields, **kwargs): diff -r 787e699871a3 -r f630610c99f0 tools/python/genwrap.py --- a/tools/python/genwrap.py Wed Jan 12 14:07:52 2011 +0000 +++ b/tools/python/genwrap.py Wed Jan 12 14:07:53 2011 +0000 @@ -4,9 +4,11 @@ import sys,os import libxltypes -(TYPE_BOOL, TYPE_INT, TYPE_UINT, TYPE_STRING) = xrange(4) +(TYPE_BOOL, TYPE_INT, TYPE_UINT, TYPE_STRING, TYPE_LIST) = xrange(5) def py_type(ty): + if isinstance(ty, libxltypes.Array): + return TYPE_LIST if ty == libxltypes.bool or isinstance(ty, libxltypes.BitField) and ty.width == 1: return TYPE_BOOL if isinstance(ty, libxltypes.Number): @@ -27,7 +29,10 @@ def py_wrapstruct(ty): l.append(' PyObject_HEAD;') l.append(' %s obj;'%ty.typename); for f in shadow_fields(ty): - l.append(' Py_%s *%s_ref;'%(f.type.rawname, f.python_name)) + if isinstance(f.type, libxltypes.Array): + l.append(' PyObject *%s_ref;'%f.python_name) + else: + l.append(' Py_%s *%s_ref;'%(f.type.rawname, f.python_name)) l.append('}Py_%s;'%ty.rawname) l.append('') return "\n".join(l) + "\n" @@ -42,7 +47,7 @@ def py_decls(ty): l.append('_hidden Py_%s *Py%s_New(void);\n'%(ty.rawname, ty.rawname)) l.append('_hidden int Py%s_Check(PyObject *self);\n'%ty.rawname) if len(shadow_fields(ty)) > 0: - l.append('_hidden void Py%s_Unshadow(Py_%s *self);\n'%(ty.rawname, ty.rawname)) + l.append('_hidden int Py%s_Unshadow(Py_%s *self);\n'%(ty.rawname, ty.rawname)) for f in ty.fields: if py_type(f.type) is not None: continue @@ -62,6 +67,15 @@ def union_check(f, ret, prefix = 'self-> u_check.append(' }') return u_check +def num_var(fname): + "Determine the name of the count variable for an array with given name" + # Yes, it's a bit of a hacky way to do it + try: + i = fname.rindex('.') + except ValueError: + return 'num_%s'%fname + return fname[:i] + 'num_' + fname[i:] + def py_attrib_get(ty, f): t = py_type(f.type) l = [] @@ -124,14 +138,22 @@ def py_attrib_set(ty, f): l.append(' return genwrap__string_set(v, (char **)&self->obj.%s);'%f.name) elif f.shadow_type is True: l.extend(u_check) - l.append(' if ( !Py%s_Check(v) ) {'%f.type.rawname) - l.append(' PyErr_SetString(PyExc_TypeError, "Expected xl.%s");'%f.type.rawname) + if isinstance(f.type, libxltypes.Array): + at = f.type.array_type + l.append(' if ( !genwrap__list_check(v, Py%s_Check) ) {'%at.rawname) + l.append(' PyErr_SetString(PyExc_TypeError, "Expected list of xl.%s");'%at.rawname) + else: + l.append(' if ( !Py%s_Check(v) ) {'%f.type.rawname) + l.append(' PyErr_SetString(PyExc_TypeError, "Expected xl.%s");'%f.type.rawname) l.append(' return -1;') l.append(' }') l.append(' if ( self->%s_ref ) {'%f.python_name) l.append(' Py_DECREF(self->%s_ref);'%f.python_name) l.append(' }') - l.append(' self->%s_ref = (Py_%s *)v;'%(f.python_name, f.type.rawname)) + if isinstance(f.type, libxltypes.Array): + l.append(' self->%s_ref = v;'%f.python_name) + else: + l.append(' self->%s_ref = (Py_%s *)v;'%(f.python_name, f.type.rawname)) l.append(' Py_INCREF(self->%s_ref);'%f.python_name) l.append(' return 0;') else: @@ -141,23 +163,88 @@ def py_attrib_set(ty, f): l.append('}') return '\n'.join(l) + "\n\n" +def list_unshadow_func(ty): + if len(shadow_fields(ty)): + uncall = ' Py%s_Unshadow(val)\n'%ty.rawname + else: + uncall = '' + + if ty.destructor_fn: + fcall = """ + for(i = 0; i < *len; i++) { + %s((*ret) + i); + } + +"""%ty.destructor_fn + else: + fcall = '' + + return """/* list of %s */ +static int %s_list_unshadow(PyObject *list, %s **ret, int *len) +{ + Py_ssize_t sz = 0, i; + %s *arr = NULL; + + if ( list == Py_None || list == NULL ) + goto out; + + if ( !PyList_Check(list) ) { + PyErr_SetString(PyExc_TypeError, "Expected list of xl.%s"); + return 0; + } + + sz = PyList_Size(list); + if ( sz <= 0 ) + goto out; + + arr = calloc(sz, sizeof(*arr)); + if ( NULL == arr ) { + PyErr_SetString(PyExc_MemoryError, "Allocating array of %s"); + return 0; + } + +out: + for(i = 0; i < sz; i++) { + Py_%s *val; + val = (Py_%s *)PyList_GetItem(list, i); +%s memcpy(arr + i, &val->obj, sizeof(val->obj)); + } +%s + free(*ret); + *ret = arr; + *len = sz; + return 1; +} + +"""%tuple([ty.typename for x in xrange(4)] + [ty.rawname for x in xrange(4)] + [uncall, fcall]) + def unshadow_func(ty): pf = shadow_fields(ty) if len(pf) == 0: return '' l = [] - l.append('void Py%s_Unshadow(Py_%s*self)\n'%(ty.rawname, ty.rawname)) + l.append('int Py%s_Unshadow(Py_%s*self)\n'%(ty.rawname, ty.rawname)) l.append('{') + l.append(' int ret = 1;') for f in pf: - l.append(' if ( self->%s_ref ) {'%f.python_name) - l.append(' Py_%s *x = (Py_%s *)self->%s_ref;'%(f.type.rawname, f.type.rawname, f.python_name)) - if len(shadow_fields(f.type)): - l.append(' Py%s_Unshadow(x);'%f.type.rawname) - l.append(' memcpy(&self->obj.%s, &x->obj, sizeof(self->obj.%s));'%(f.name, f.name)) - l.append(' }else{') - l.append(' memset(&self->obj.%s, 0, sizeof(self->obj.%s));'%(f.name, f.name)) - l.append(' }') + if isinstance(f.type, libxltypes.Array): + at = f.type.array_type + l.append(' if ( !%s_list_unshadow(self->%s_ref, '%(at.typename, f.python_name)) + l.append(' &self->obj.%s, '%f.name) + l.append(' &self->obj.%s) )'%num_var(f.name)) + l.append(' ret = 0;') + else: + l.append(' if ( self->%s_ref ) {'%f.python_name) + l.append(' Py_%s *x = (Py_%s *)self->%s_ref;'%(f.type.rawname, f.type.rawname, f.python_name)) + if len(shadow_fields(f.type)): + l.append(' if ( !Py%s_Unshadow(x) )'%f.type.rawname) + l.append(' ret = 0;') + l.append(' memcpy(&self->obj.%s, &x->obj, sizeof(self->obj.%s));'%(f.name, f.name)) + l.append(' }else{') + l.append(' memset(&self->obj.%s, 0, sizeof(self->obj.%s));'%(f.name, f.name)) + l.append(' }') + l.append(' return ret;') l.append('}') l.append('') return '\n'.join(l) @@ -183,6 +270,7 @@ static PyObject *Py%s_new(PyTypeObject * funcs += unshadow_func(ty) + l.append('') l.append('static void Py%s_dealloc(Py_%s *self)'%(ty.rawname, ty.rawname)) l.append('{') for f in ty.fields: @@ -193,8 +281,12 @@ static PyObject *Py%s_new(PyTypeObject * l.append(' if ( self->%s_ref ) {'%f.python_name) l.append(' Py_DECREF(self->%s_ref);'%f.python_name) l.append(' }') - # prevent libxl destructor from double freeing shadowed struct - l.append(' memset(&self->obj.%s, 0, sizeof(self->obj.%s));'%(f.name, f.name)) + if isinstance(f.type, libxltypes.Array): + l.append(' self->obj.%s = NULL;'%f.name) + l.append(' self->obj.%s = 0;'%num_var(f.name)) + else: + # prevent libxl destructor from double freeing shadowed struct + l.append(' memset(&self->obj.%s, 0, sizeof(self->obj.%s));'%(f.name, f.name)) if ty.destructor_fn is not None: l.append(' %s(&self->obj);'%ty.destructor_fn) @@ -286,7 +378,7 @@ def dbg_tree(str, indent=0): # We don't have a good translation for anonymous structures so we just # flatten them out recursively and replace '.' with '_'. For example # domain_build_info.u.hvm.pae becomes domain_build_info.u_hvm_pae -def flatten_type(ty, path = None, depth = 0, condvar = []): +def flatten_type(ty, sdict, path = None, depth = 0, condvar = []): if not isinstance(ty, libxltypes.Aggregate): return ty.fields @@ -302,6 +394,9 @@ def flatten_type(ty, path = None, depth if isinstance(f.type, libxltypes.Aggregate) and \ f.type.typename is not None: f.shadow_type = True + elif isinstance(f.type, libxltypes.Array): + sdict[f.type.array_type] = None + f.shadow_type = True else: f.shadow_type = False @@ -315,7 +410,7 @@ def flatten_type(ty, path = None, depth dbg_tree('(%s)'%(f.name), depth + 1) if isinstance(ty, libxltypes.KeyedUnion): condvar.append((f.keyvar_expr, ty.keyvar_name)) - ret.extend(flatten_type(f.type, f.name, depth + 1, condvar)) + ret.extend(flatten_type(f.type, sdict, f.name, depth + 1, condvar)) if isinstance(ty, libxltypes.KeyedUnion): condvar.pop() else: @@ -325,13 +420,14 @@ def flatten_type(ty, path = None, depth return ret -def frob_type(type): +def frob_type(type, sdict): dbg_tree('[%s]'%type.typename) - type.fields = flatten_type(type) + type.fields = flatten_type(type, sdict) return type def frob_types(types): - return map(frob_type, types) + sdict = {} + return (map(lambda x:frob_type(x, sdict), types), sdict) if __name__ == '__main__': if len(sys.argv) < 4: @@ -341,7 +437,7 @@ if __name__ == '__main__': idl = sys.argv[1] (_,types) = libxltypes.parse(idl) - types = frob_types(types) + (types, sdict) = frob_types(types) decls = sys.argv[2] f = open(decls, 'w') @@ -371,6 +467,9 @@ _hidden void genwrap__init(PyObject *m); /* Generic type initialiser */ _hidden int genwrap__obj_init(PyObject *self, PyObject *args, PyObject *kwds); +/* Generic checker for list wrapper */ +_hidden int genwrap__list_check(PyObject *list, int(*cbfn)(PyObject *obj)); + /* Auto-generated get/set functions for simple data-types */ _hidden int genwrap__string_set(PyObject *v, char **str); _hidden PyObject *genwrap__string_get(char **str); @@ -406,6 +505,8 @@ _hidden int genwrap__ll_set(PyObject *v, #include "%s" """ % tuple((' '.join(sys.argv),) + (os.path.split(decls)[-1:]),)) + for ty in sdict.keys(): + f.write(list_unshadow_func(ty)) for ty in types: f.write('/* Attribute get/set functions for %s */\n'%ty.typename) for a in ty.fields: diff -r 787e699871a3 -r f630610c99f0 tools/python/xen/lowlevel/xl/xl.c --- a/tools/python/xen/lowlevel/xl/xl.c Wed Jan 12 14:07:52 2011 +0000 +++ b/tools/python/xen/lowlevel/xl/xl.c Wed Jan 12 14:07:53 2011 +0000 @@ -73,6 +73,25 @@ int genwrap__obj_init(PyObject *self, Py return 0; } +int genwrap__list_check(PyObject *list, int(*cbfn)(PyObject *obj)) +{ + Py_ssize_t i, len; + + if ( list == Py_None ) + return 1; + + if ( !PyList_Check(list) ) + return 0; + + len = PyList_Size(list); + for(i = 0; i < len; i++) { + if ( !(*cbfn)(PyList_GetItem(list, i)) ) + return 0; + } + + return 1; +} + int genwrap__string_set(PyObject *v, char **str) { char *tmp; _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |