[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH,RFC]: libxl python binding



Attached patch is the first-cut of a libxl python binding. Presently
only list_domains, domid_to_name, domain_shutdown and domain_destroy are
implemented. The code takes advantage of Ian Campbells libxl IDL work to
make 178 lines of python generate 4,460 lines of boilerplate.

All that remains is:
 - support marshalling of other than integer types
 - call auto-generated C destructors when python objects are free'd
 - flatten out unions, structs etc. for libxl-type marshalling
 - manually implement a xen.lowlevel.xl.ctx method for each libxl function

Here's an example of what current code can do:

$ sudo python
>>> from xen.lowlevel import xl
>>> xl
<module 'xen.lowlevel.xl' from 
'/usr/lib/python2.6/dist-packages/xen/lowlevel/xl.so'>
>>> dir(xl)
['Error', '__doc__', '__file__', '__name__', '__package__', 'ctx', 
'device_console', 'device_disk', 'device_model_info', 'device_net2', 
'device_nic', 'device_pci', 'device_vfb', 'device_vkb', 'diskinfo', 
'domain_build_info', 'domain_build_state', 'domain_create_info', 'dominfo', 
'file_reference', 'net2info', 'nicinfo', 'physinfo', 'poolinfo', 
'sched_credit', 'vcpuinfo', 'version_info', 'vminfo']
>>> ctx = xl.ctx()
>>> dir(ctx)
['domain_destroy', 'domain_shutdown', 'domid_to_name', 'list_domains']
>>> ctx.list_domains()
[<xen.lowlevel.xl.dominfo object at 0x7f6765492a08>, <xen.lowlevel.xl.dominfo 
object at 0x7f6765492a50>, <xen.lowlevel.xl.dominfo object at 0x7f6765492a98>]
>>> map(lambda x:x.domid, ctx.list_domains())
[0L, 133L, 136L]
>>> map(ctx.domid_to_name, map(lambda x:x.domid, ctx.list_domains()))
['Domain-0', 'netbsd', 'lenny']
>>> ctx.domain_destroy(136)
>>> map(ctx.domid_to_name, map(lambda x:x.domid, ctx.list_domains()))
['Domain-0', 'netbsd']

-----

 tools/python/genwrap.py             |  178 +++++++++++++++++++++++
 tools/python/xen/lowlevel/xl/xl.c   |  269 ++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl.idl               |   10 -
 tools/libxl/libxltypes.py           |   23 ++-
 tools/python/Makefile               |    1 
 tools/python/setup.py               |   19 ++
 6 files changed, 486 insertions(+), 14 deletions(-)

----8<-----------------------------------------------------------------
diff -r d11a52daace3 tools/libxl/libxl.idl
--- a/tools/libxl/libxl.idl     Mon Sep 06 15:16:03 2010 +0100
+++ b/tools/libxl/libxl.idl     Tue Sep 07 15:22:24 2010 +0100
@@ -6,11 +6,11 @@
 libxl_ctx = Builtin("ctx")
 libxl_uuid = Builtin("uuid")
 libxl_mac = Builtin("mac")
-libxl_qemu_machine_type = Builtin("qemu_machine_type")
-libxl_console_consback = Builtin("console_consback")
-libxl_console_constype = Builtin("console_constype")
-libxl_disk_phystype = Builtin("disk_phystype")
-libxl_nic_type = Builtin("nic_type")
+libxl_qemu_machine_type = Number("qemu_machine_type", namespace="libxl_")
+libxl_console_consback = Number("console_consback", namespace="libxl_")
+libxl_console_constype = Number("console_constype", namespace="libxl_")
+libxl_disk_phystype = Number("disk_phystype", namespace="libxl_")
+libxl_nic_type = Number("nic_type", namespace="libxl_")
 
 libxl_string_list = Builtin("string_list", 
destructor_fn="libxl_string_list_destroy", passby=PASS_BY_REFERENCE)
 libxl_key_value_list = Builtin("key_value_list", 
destructor_fn="libxl_key_value_list_destroy", passby=PASS_BY_REFERENCE)
diff -r d11a52daace3 tools/libxl/libxltypes.py
--- a/tools/libxl/libxltypes.py Mon Sep 06 15:16:03 2010 +0100
+++ b/tools/libxl/libxltypes.py Tue Sep 07 15:22:24 2010 +0100
@@ -14,10 +14,13 @@ class Type(object):
 
         if typename is None: # Anonymous type
             self.typename = None
+            self.rawname = None
         elif self.namespace is None: # e.g. system provided types
             self.typename = typename
+            self.rawname = typename
         else:
             self.typename = self.namespace + typename
+            self.rawname = typename
 
         if self.typename is not None:
             self.destructor_fn = kwargs.setdefault('destructor_fn', 
self.typename + "_destroy")
@@ -32,11 +35,17 @@ class Builtin(Type):
         kwargs.setdefault('destructor_fn', None)
         Type.__init__(self, typename, **kwargs)
 
-class UInt(Type):
+class Number(Builtin):
+    def __init__(self, ctype, **kwargs):
+        kwargs.setdefault('namespace', None)
+        kwargs.setdefault('destructor_fn', None)
+        Builtin.__init__(self, ctype, **kwargs)
+
+class UInt(Number):
     def __init__(self, w, **kwargs):
         kwargs.setdefault('namespace', None)
         kwargs.setdefault('destructor_fn', None)
-        Type.__init__(self, "uint%d_t" % w, **kwargs)
+        Number.__init__(self, "uint%d_t" % w, **kwargs)
 
         self.width = w
 
@@ -128,12 +137,12 @@ class Reference(Type):
 
 void = Builtin("void *", namespace = None)
 bool = Builtin("bool", namespace = None)
-size_t = Builtin("size_t", namespace = None)
+size_t = Number("size_t", namespace = None)
 
-integer = Builtin("int", namespace = None)
-unsigned_integer = Builtin("unsigned int", namespace = None)
-unsigned = Builtin("unsigned int", namespace = None)
-unsigned_long = Builtin("unsigned long", namespace = None)
+integer = Number("int", namespace = None)
+unsigned_integer = Number("unsigned int", namespace = None)
+unsigned = Number("unsigned int", namespace = None)
+unsigned_long = Number("unsigned long", namespace = None)
 
 uint8 = UInt(8)
 uint16 = UInt(16)
diff -r d11a52daace3 tools/python/Makefile
--- a/tools/python/Makefile     Mon Sep 06 15:16:03 2010 +0100
+++ b/tools/python/Makefile     Tue Sep 07 15:22:24 2010 +0100
@@ -59,6 +59,7 @@ refresh-po: $(POTFILE)
 
 .PHONY: install
 install: install-messages install-dtd
+       PYTHONPATH=$(XEN_ROOT)/tools/libxl $(PYTHON) genwrap.py 
$(XEN_ROOT)/tools/libxl/libxl.idl __pyxl_types.h
        CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py install \
                $(PYTHON_PREFIX_ARG) --root="$(DESTDIR)" --force
 
diff -r d11a52daace3 tools/python/genwrap.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/genwrap.py   Tue Sep 07 15:22:24 2010 +0100
@@ -0,0 +1,178 @@
+#!/usr/bin/python
+
+import sys
+import re
+
+import libxltypes
+
+def py_wrapstruct(ty):
+    l = []
+    l.append("typedef struct {")
+    l.append("    PyObject_HEAD;")
+    l.append("    %s obj;"%ty.typename);
+    l.append("}Py_%s;"%ty.rawname)
+    l.append("")
+    return "\n".join(l) + "\n\n"
+
+def py_type(ty):
+    if ty == libxltypes.bool or isinstance(ty, libxltypes.BitField) and 
ty.width == 1:
+        return "Bool"
+    if isinstance(ty, libxltypes.Number):
+        # FIXME: support unsigned properly
+        return "Int"
+    if ty == libxltypes.string:
+        return "String"
+    return None
+
+def py_attrib_get(ty, f):
+    if f.name == None:
+        return ""
+    t = py_type(f.type)
+    l = []
+    l.append("static PyObject *py_%s_%s_get(Py_%s *self, void 
*priv)"%(ty.rawname, f.name, ty.rawname))
+    l.append("{")
+    if t == "Int":
+        l.append("    return PyLong_FromUnsignedLong(self->obj.%s);"%f.name)
+    else:
+        l.append("    // %s"%t)
+        l.append("    return NULL;")
+    l.append("}")
+    return '\n'.join(l) + "\n\n"
+
+def py_attrib_set(ty, f):
+    if f.name == None:
+        return ""
+    t = py_type(f.type)
+    l = []
+    l.append("static int py_%s_%s_set(Py_%s *self, PyObject *v, void 
*priv)"%(ty.rawname, f.name, ty.rawname))
+    l.append("{")
+    if t == "Int":
+        l.append("    self->obj.%s = PyLong_AsLongLong(v);"%f.name)
+        l.append("    return 0;")
+    else:
+        l.append("    // %s"%t)
+        l.append("    return -1;")
+    l.append("}")
+    return '\n'.join(l) + "\n\n"
+
+def py_object_def(ty):
+    l = []
+    funcs="""
+static void Py%s_dealloc(Py_%s *self)
+{
+    self->ob_type->tp_free((PyObject *)self);
+}
+
+static int Py%s_init(Py_%s *self, PyObject *args, PyObject *kwds)
+{
+    return 0;
+}
+
+static PyObject *Py%s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    Py_%s *self = (Py_%s *)type->tp_alloc(type, 0);
+    if (self == NULL)
+        return NULL;
+    memset(&self->obj, 0, sizeof(self->obj));
+    return (PyObject *)self;
+}
+"""%tuple(ty.rawname for x in range(7))
+
+    l.append("static PyGetSetDef Py%s_getset[] = {"%ty.rawname)
+    for f in ty.fields:
+        if f.name == None:
+            continue
+        l.append("    { .name = \"%s\", "%f.name)
+        l.append("      .get = (getter)py_%s_%s_get, "%(ty.rawname, f.name))
+        l.append("      .set = (setter)py_%s_%s_set },"%(ty.rawname, f.name))
+    l.append("    { .name = NULL }")
+    l.append("};")
+    struct="""
+static PyTypeObject Py%s_Type= {
+    PyObject_HEAD_INIT(NULL)
+    0,
+    PKG ".%s",
+    sizeof(Py_%s),
+    0,
+    (destructor)Py%s_dealloc,     /* tp_dealloc        */
+    NULL,                         /* tp_print          */
+    NULL,                         /* tp_getattr        */
+    NULL,                         /* tp_setattr        */
+    NULL,                         /* tp_compare        */
+    NULL,                         /* tp_repr           */
+    NULL,                         /* tp_as_number      */
+    NULL,                         /* tp_as_sequence    */
+    NULL,                         /* tp_as_mapping     */
+    NULL,                         /* tp_hash           */
+    NULL,                         /* tp_call           */
+    NULL,                         /* tp_str            */
+    NULL,                         /* tp_getattro       */
+    NULL,                         /* tp_setattro       */
+    NULL,                         /* tp_as_buffer      */
+    Py_TPFLAGS_DEFAULT,           /* tp_flags          */
+    "%s",                         /* tp_doc            */
+    NULL,                         /* tp_traverse       */
+    NULL,                         /* tp_clear          */
+    NULL,                         /* tp_richcompare    */
+    0,                            /* tp_weaklistoffset */
+    NULL,                         /* tp_iter           */
+    NULL,                         /* tp_iternext       */
+    NULL,                         /* tp_methods        */
+    NULL,                         /* tp_members        */
+    Py%s_getset,                  /* tp_getset         */
+    NULL,                         /* tp_base           */
+    NULL,                         /* tp_dict           */
+    NULL,                         /* tp_descr_get      */
+    NULL,                         /* tp_descr_set      */
+    0,                            /* tp_dictoffset     */
+    (initproc)Py%s_init,          /* tp_init           */
+    NULL,                         /* tp_alloc          */
+    Py%s_new,                     /* tp_new            */
+};
+
+"""%tuple(ty.rawname for x in range(8))
+    return funcs + '\n'.join(l) + "\n\n" + struct
+
+def py_initfuncs(types):
+    l = []
+    l.append("static void gentypes__init(PyObject *m)")
+    l.append("{")
+    for ty in types:
+        l.append("    if (PyType_Ready(&Py%s_Type) >= 0) {"%ty.rawname)
+        l.append("        Py_INCREF(&Py%s_Type);"%ty.rawname)
+        l.append("        PyModule_AddObject(m, \"%s\", (PyObject 
*)&Py%s_Type);"%(ty.rawname, ty.rawname))
+        l.append("    }")
+    l.append("}")
+    return '\n'.join(l) + "\n\n"
+
+if __name__ == '__main__':
+    if len(sys.argv) < 3:
+        print >>sys.stderr, "Usage: genwrap.py <idl> <pythonwrapper>"
+        sys.exit(1)
+
+    idl = sys.argv[1]
+    (_,types) = libxltypes.parse(idl)
+ 
+    wrapper = sys.argv[2]
+    f = open(wrapper, "w")
+    f.write("""#ifndef __PYXL_TYPES_H
+#define __PYXL_TYPES_H
+
+/*
+ * DO NOT EDIT.
+ *
+ * This file is autogenerated by
+ * "%s"
+ */
+ 
+""" % " ".join(sys.argv))
+    for ty in types:
+        f.write("/* Attribute get/set functions for %s */\n"%ty.typename)
+        f.write(py_wrapstruct(ty))
+        for a in ty.fields:
+            f.write(py_attrib_get(ty,a))
+            f.write(py_attrib_set(ty,a))
+        f.write(py_object_def(ty))
+    f.write(py_initfuncs(types))
+    f.write("""#endif /* __PYXL_TYPES_H */\n""")
+    f.close()
diff -r d11a52daace3 tools/python/setup.py
--- a/tools/python/setup.py     Mon Sep 06 15:16:03 2010 +0100
+++ b/tools/python/setup.py     Tue Sep 07 15:22:24 2010 +0100
@@ -9,14 +9,23 @@ extra_compile_args  = [ "-fno-strict-ali
 include_dirs = [ XEN_ROOT + "/tools/libxc",
                  XEN_ROOT + "/tools/xenstore",
                  XEN_ROOT + "/tools/include",
+                 XEN_ROOT + "/tools/libxl",
                  ]
 
 library_dirs = [ XEN_ROOT + "/tools/libxc",
                  XEN_ROOT + "/tools/xenstore",
+                 XEN_ROOT + "/tools/libxl",
+                 XEN_ROOT + "/tools/blktap2/control",
                  ]
 
 libraries = [ "xenctrl", "xenguest", "xenstore" ]
 
+plat = os.uname()[0]
+if plat == 'Linux':
+    uuid_libs = ["uuid"]
+else:
+    uuid_libs = []
+
 xc = Extension("xc",
                extra_compile_args = extra_compile_args,
                include_dirs       = include_dirs + [ "xen/lowlevel/xc" ],
@@ -83,8 +92,14 @@ netlink = Extension("netlink",
                     sources            = [ "xen/lowlevel/netlink/netlink.c",
                                            
"xen/lowlevel/netlink/libnetlink.c"])
 
-modules = [ xc, xs, ptsname, acm, flask ]
-plat = os.uname()[0]
+xl = Extension("xl",
+               extra_compile_args = extra_compile_args,
+               include_dirs       = include_dirs + [ "xen/lowlevel/xl" ],
+               library_dirs       = library_dirs,
+               libraries          = libraries + ["xenlight", "blktapctl" ] + 
uuid_libs,
+               sources            = [ "xen/lowlevel/xl/xl.c" ])
+
+modules = [ xc, xs, ptsname, acm, flask, xl ]
 if plat == 'SunOS':
     modules.extend([ scf, process ])
 if plat == 'Linux':
diff -r d11a52daace3 tools/python/xen/lowlevel/xl/xl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/lowlevel/xl/xl.c Tue Sep 07 15:22:24 2010 +0100
@@ -0,0 +1,269 @@
+/******************************************************************************
+ * xl.c
+ * 
+ * Copyright (c) 2010 Citrix Ltd.
+ * Author: Gianni Tedesco
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <Python.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <xenctrl.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+
+#include <libxl.h>
+#include <libxl_utils.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/* Needed for Python versions earlier than 2.3. */
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC DL_EXPORT(void)
+#endif
+
+#define PKG "xen.lowlevel.xl"
+#define CLS "ctx"
+
+static PyObject *xl_error_obj;
+
+#include "_pyxl_types.h"
+
+typedef struct {
+    PyObject_HEAD;
+    libxl_ctx ctx;
+    xentoollog_logger_stdiostream *logger;
+    xentoollog_level minmsglevel;
+} XlObject;
+
+static PyObject *pyxl_list_domains(XlObject *self)
+{
+    libxl_dominfo *cur, *info;
+    PyObject *list;
+    int nr_dom, i;
+
+    info = libxl_list_domain(&self->ctx, &nr_dom);
+    if ( NULL == info )
+        return PyList_New(0);
+
+    list = PyList_New(nr_dom);
+    if ( NULL == list )
+        goto err_mem;
+
+    for(i = 0, cur = info; i < nr_dom; i++, cur++) {
+        Py_dominfo *di;
+        di = (Py_dominfo *)Pydominfo_new(&Pydominfo_Type, NULL, NULL);
+        if ( NULL == di )
+            goto err_mem;
+        memcpy(&di->obj, cur, sizeof(di->obj));
+        PyList_SetItem(list, i, (PyObject *)di);
+    }
+
+    free(info);
+    return list;
+err_mem:
+    Py_DECREF(list);
+    PyErr_SetString(PyExc_MemoryError, "Allocating domain list");
+    return NULL;
+}
+
+static PyObject *pyxl_domid_to_name(XlObject *self, PyObject *args)
+{
+    char *domname;
+    int domid;
+    PyObject *ret;
+
+    if ( !PyArg_ParseTuple(args, "i", &domid) )
+        return NULL;
+
+    domname = libxl_domid_to_name(&self->ctx, domid);
+    ret = PyString_FromString(domname);
+    free(domname);
+
+    return ret;
+}
+
+static PyObject *pyxl_domain_shutdown(XlObject *self, PyObject *args)
+{
+    int domid, req = 0;
+    if ( !PyArg_ParseTuple(args, "i|i", &domid, &req) )
+        return NULL;
+    if ( libxl_domain_shutdown(&self->ctx, domid, req) ) {
+        PyErr_SetString(xl_error_obj, "cannot shutdown domain");
+        return NULL;
+    }
+    return Py_None;
+}
+
+static PyObject *pyxl_domain_destroy(XlObject *self, PyObject *args)
+{
+    int domid, force = 1;
+    if ( !PyArg_ParseTuple(args, "i|i", &domid, &force) )
+        return NULL;
+    if ( libxl_domain_destroy(&self->ctx, domid, force) ) {
+        PyErr_SetString(xl_error_obj, "cannot destroy domain");
+        return NULL;
+    }
+    return Py_None;
+}
+
+static PyMethodDef pyxl_methods[] = {
+    {"list_domains", (PyCFunction)pyxl_list_domains, METH_NOARGS,
+         "List domains"},
+    {"domid_to_name", (PyCFunction)pyxl_domid_to_name, METH_VARARGS,
+         "Retrieve name from domain-id"},
+    {"domain_shutdown", (PyCFunction)pyxl_domain_shutdown, METH_VARARGS,
+         "Shutdown a domain"},
+    {"domain_destroy", (PyCFunction)pyxl_domain_destroy, METH_VARARGS,
+         "Destroy a domain"},
+    { NULL, NULL, 0, NULL }
+};
+
+static PyObject *PyXl_getattr(PyObject *obj, char *name)
+{
+    return Py_FindMethod(pyxl_methods, obj, name);
+}
+
+static PyObject *PyXl_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    XlObject *self = (XlObject *)type->tp_alloc(type, 0);
+
+    if (self == NULL)
+        return NULL;
+
+    memset(&self->ctx, 0, sizeof(self->ctx));
+    self->logger = NULL;
+    self->minmsglevel = XTL_PROGRESS;
+
+    return (PyObject *)self;
+}
+
+static int
+PyXl_init(XlObject *self, PyObject *args, PyObject *kwds)
+{
+    self->logger = xtl_createlogger_stdiostream(stderr, self->minmsglevel,  0);
+    if (!self->logger) {
+        PyErr_SetString(xl_error_obj, "cannot init xl logger");
+        return -1;
+    }
+
+    if ( libxl_ctx_init(&self->ctx, LIBXL_VERSION,
+                (xentoollog_logger*)self->logger) ) {
+        PyErr_SetString(xl_error_obj, "cannot init xl context");
+        return -1;
+    }
+
+    return 0;
+}
+
+static void PyXl_dealloc(XlObject *self)
+{
+    libxl_ctx_free(&self->ctx);
+    if ( self->logger )
+        xtl_logger_destroy((xentoollog_logger*)self->logger);
+
+    self->ob_type->tp_free((PyObject *)self);
+}
+
+static PyTypeObject PyXlType = {
+    PyObject_HEAD_INIT(NULL)
+    0,
+    PKG "." CLS,
+    sizeof(XlObject),
+    0,
+    (destructor)PyXl_dealloc,     /* tp_dealloc        */
+    NULL,                         /* tp_print          */
+    PyXl_getattr,                 /* tp_getattr        */
+    NULL,                         /* tp_setattr        */
+    NULL,                         /* tp_compare        */
+    NULL,                         /* tp_repr           */
+    NULL,                         /* tp_as_number      */
+    NULL,                         /* tp_as_sequence    */
+    NULL,                         /* tp_as_mapping     */
+    NULL,                         /* tp_hash           */
+    NULL,                         /* tp_call           */
+    NULL,                         /* tp_str            */
+    NULL,                         /* tp_getattro       */
+    NULL,                         /* tp_setattro       */
+    NULL,                         /* tp_as_buffer      */
+    Py_TPFLAGS_DEFAULT,           /* tp_flags          */
+    "libxenlight connection",     /* tp_doc            */
+    NULL,                         /* tp_traverse       */
+    NULL,                         /* tp_clear          */
+    NULL,                         /* tp_richcompare    */
+    0,                            /* tp_weaklistoffset */
+    NULL,                         /* tp_iter           */
+    NULL,                         /* tp_iternext       */
+    pyxl_methods,                 /* tp_methods        */
+    NULL,                         /* tp_members        */
+    NULL,                         /* tp_getset         */
+    NULL,                         /* tp_base           */
+    NULL,                         /* tp_dict           */
+    NULL,                         /* tp_descr_get      */
+    NULL,                         /* tp_descr_set      */
+    0,                            /* tp_dictoffset     */
+    (initproc)PyXl_init,          /* tp_init           */
+    NULL,                         /* tp_alloc          */
+    PyXl_new,                     /* tp_new            */
+};
+
+static PyMethodDef xl_methods[] = { { NULL } };
+
+PyMODINIT_FUNC initxl(void)
+{
+    PyObject *m;
+
+    if (PyType_Ready(&PyXlType) < 0)
+        return;
+
+    m = Py_InitModule(PKG, xl_methods);
+
+    if (m == NULL)
+      return;
+
+    xl_error_obj = PyErr_NewException(PKG ".Error", PyExc_RuntimeError, NULL);
+
+    Py_INCREF(&PyXlType);
+    PyModule_AddObject(m, CLS, (PyObject *)&PyXlType);
+
+    Py_INCREF(xl_error_obj);
+    PyModule_AddObject(m, "Error", xl_error_obj);
+
+    gentypes__init(m);
+}
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ */



_______________________________________________
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®.