[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.