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 2 of 4] xl: support array types in IDL

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 2 of 4] xl: support array types in IDL
From: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx>
Date: Wed, 12 Jan 2011 14:19:00 +0000
Cc: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>, Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
Delivery-date: Wed, 12 Jan 2011 06:33:41 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1294841938@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.1294841938@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           |  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