WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 08 of 10] xl: support array types in IDL

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 08 of 10] xl: support array types in IDL
From: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx>
Date: Tue, 11 Jan 2011 16:03:21 +0000
Cc: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>
Delivery-date: Tue, 11 Jan 2011 08:19:27 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1294761793@xxxxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <patchbomb.1294761793@xxxxxxxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mercurial-patchbomb/1.6.3
 tools/libxl/gentypes.py           |   30 +++++++-
 tools/libxl/libxltypes.py         |    6 +
 tools/python/genwrap.py           |  156 +++++++++++++++++++++++++++++++------
 tools/python/xen/lowlevel/xl/xl.c |   19 ++++
 4 files changed, 183 insertions(+), 28 deletions(-)


# HG changeset patch
# User Gianni Tedesco <gianni.tedesco@xxxxxxxxxx>
# Date 1294761668 0
# Node ID 9c57b1622bbcc6252e59d18dca5e33673d6fc236
# Parent  735df86eab9a758431f9a3927db64e02baae82d6
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 735df86eab9a -r 9c57b1622bbc tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py   Tue Jan 11 16:01:08 2011 +0000
+++ b/tools/libxl/gentypes.py   Tue Jan 11 16:01:08 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 735df86eab9a -r 9c57b1622bbc tools/libxl/libxltypes.py
--- a/tools/libxl/libxltypes.py Tue Jan 11 16:01:08 2011 +0000
+++ b/tools/libxl/libxltypes.py Tue Jan 11 16:01:08 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 735df86eab9a -r 9c57b1622bbc tools/python/genwrap.py
--- a/tools/python/genwrap.py   Tue Jan 11 16:01:08 2011 +0000
+++ b/tools/python/genwrap.py   Tue Jan 11 16:01:08 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, &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 sync_func(ty):
+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)
@@ -181,18 +268,24 @@ static PyObject *Py%s_new(PyTypeObject *
 
 """%tuple(ty.rawname for x in range(5))
 
-    funcs += sync_func(ty)
+    funcs += unshadow_func(ty)
 
-
+    l.append('')
     l.append('static void Py%s_dealloc(Py_%s *self)'%(ty.rawname, ty.rawname))
     l.append('{')
-    if ty.destructor_fn is not None:
-        l.append('    %s(&self->obj);'%ty.destructor_fn)
     for f in shadow_fields(ty):
         l.append('    if ( self->%s_ref ) {'%f.python_name)
         l.append('        Py_DECREF(self->%s_ref);'%f.python_name)
         l.append('    }')
-    l.append('self->ob_type->tp_free((PyObject *)self);')
+        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:
+            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)
+    l.append('    self->ob_type->tp_free((PyObject *)self);')
     l.append('}')
     l.append('')
 
@@ -279,7 +372,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
 
@@ -295,6 +388,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
 
@@ -308,7 +404,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:
@@ -318,13 +414,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:
@@ -334,7 +431,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')
@@ -364,6 +461,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);
@@ -399,6 +499,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 735df86eab9a -r 9c57b1622bbc tools/python/xen/lowlevel/xl/xl.c
--- a/tools/python/xen/lowlevel/xl/xl.c Tue Jan 11 16:01:08 2011 +0000
+++ b/tools/python/xen/lowlevel/xl/xl.c Tue Jan 11 16:01:08 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