qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface f


From: Balamuruhan S
Subject: [Qemu-devel] [RFC PATCH 1/6] utils/python_api: add scripting interface for Qemu with python lib
Date: Wed, 7 Aug 2019 12:44:40 +0530

Adds scripting interface with python library to call functions in
python modules from Qemu that can be used to feed input externally
and without recompiling Qemu that can be used for early development,
testing and can be extended to abstract some of Qemu code out to a
python script to ease maintenance.

Signed-off-by: Balamuruhan S <address@hidden>
---
 configure                   |  10 +++++
 include/sysemu/python_api.h |  30 +++++++++++++
 util/Makefile.objs          |   1 +
 util/python_api.c           | 100 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 141 insertions(+)
 create mode 100644 include/sysemu/python_api.h
 create mode 100644 util/python_api.c

diff --git a/configure b/configure
index 714e7fb6a1..fddddcc879 100755
--- a/configure
+++ b/configure
@@ -1866,6 +1866,11 @@ fi
 # Preserve python version since some functionality is dependent on it
 python_version=$($python -V 2>&1 | sed -e 's/Python\ //')
 
+# Python config to be used for CFLAGS and LDFLAGS
+if ! [ -z "$python" ]; then
+    python_config="$python-config"
+fi
+
 # Suppress writing compiled files
 python="$python -B"
 
@@ -6304,6 +6309,11 @@ echo_version() {
     fi
 }
 
+if ! [ -z "$python_config" ]; then
+    QEMU_CFLAGS="$QEMU_CFLAGS $($python_config --includes)"
+    QEMU_LDFLAGS="$QEMU_LDFLAGS $($python_config --ldflags)"
+fi
+
 # prepend pixman and ftd flags after all config tests are done
 QEMU_CFLAGS="$pixman_cflags $fdt_cflags $QEMU_CFLAGS"
 QEMU_LDFLAGS="$fdt_ldflags $QEMU_LDFLAGS"
diff --git a/include/sysemu/python_api.h b/include/sysemu/python_api.h
new file mode 100644
index 0000000000..ff02d58377
--- /dev/null
+++ b/include/sysemu/python_api.h
@@ -0,0 +1,30 @@
+#ifndef _PPC_PNV_PYTHON_H
+#define _PPC_PNV_PYTHON_H
+
+#include <stdbool.h>
+#include <Python.h>
+
+extern PyObject *python_callback(const char *abs_module_path, const char *mod,
+                                 const char *func, char *args[],
+                                 const int nargs);
+
+extern uint64_t python_callback_int(const char *abs_module_path,
+                                    const char *mod,
+                                    const char *func, char *args[],
+                                    const int nargs);
+
+extern char *python_callback_str(const char *abs_module_path, const char *mod,
+                                 const char *func, char *args[],
+                                 const int nargs);
+
+extern bool python_callback_bool(const char *abs_module_path, const char *mod,
+                                 const char *func, char *args[],
+                                 const int nargs);
+
+extern void python_args_init_cast_int(char *args[], int arg, int pos);
+
+extern void python_args_init_cast_long(char *args[], uint64_t arg, int pos);
+
+extern void python_args_clean(char *args[], int nargs);
+
+#endif
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 41bf59d127..05851c94a7 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -50,6 +50,7 @@ util-obj-y += range.o
 util-obj-y += stats64.o
 util-obj-y += systemd.o
 util-obj-y += iova-tree.o
+util-obj-y += python_api.o
 util-obj-$(CONFIG_INOTIFY1) += filemonitor-inotify.o
 util-obj-$(CONFIG_LINUX) += vfio-helpers.o
 util-obj-$(CONFIG_POSIX) += drm.o
diff --git a/util/python_api.c b/util/python_api.c
new file mode 100644
index 0000000000..854187e00f
--- /dev/null
+++ b/util/python_api.c
@@ -0,0 +1,100 @@
+#include "sysemu/python_api.h"
+#include "qemu/osdep.h"
+
+PyObject *python_callback(const char *abs_module_path, const char *mod,
+                          const char *func, char *args[], const int nargs)
+{
+    PyObject *mod_name, *module, *mod_ref, *function, *arguments;
+    PyObject *result = 0;
+    PyObject *value = NULL;
+
+    /* Set PYTHONPATH to absolute module path directory */
+    if (!abs_module_path)
+        abs_module_path = ".";
+    setenv("PYTHONPATH", abs_module_path, 1);
+
+    /* Initialize the Python Interpreter */
+    Py_Initialize();
+    mod_name = PyUnicode_FromString(mod);
+    /* Import module object */
+    module = PyImport_Import(mod_name);
+    if (!module) {
+        PyErr_Print();
+        fprintf(stderr, "Failed to load \"%s\"\n", mod);
+        exit(EXIT_FAILURE);
+    }
+    mod_ref = PyModule_GetDict(module);
+    function = PyDict_GetItemString(mod_ref, func);
+    if (function && PyCallable_Check(function)) {
+        arguments = PyTuple_New(nargs);
+        for (int i = 0; i < nargs; i++) {
+            value = PyUnicode_FromString(args[i]);
+            if (!value) {
+                Py_DECREF(arguments);
+                Py_DECREF(module);
+                fprintf(stderr, "Cannot convert argument\n");
+                exit(EXIT_FAILURE);
+            }
+            PyTuple_SetItem(arguments, i, value);
+        }
+        PyErr_Print();
+        result = PyObject_CallObject(function, arguments);
+        PyErr_Print();
+    }
+    else {
+        if (PyErr_Occurred())
+            PyErr_Print();
+        fprintf(stderr, "Cannot find function \"%s\"\n", func);
+        exit(EXIT_FAILURE);
+    }
+    /* Clean up */
+    Py_DECREF(value);
+    Py_DECREF(module);
+    Py_DECREF(mod_name);
+    /* Finish the Python Interpreter */
+    Py_Finalize();
+    return result;
+}
+
+uint64_t python_callback_int(const char *abs_module_path, const char *mod,
+                             const char *func, char *args[], const int nargs)
+{
+    PyObject *result;
+    result = python_callback(abs_module_path, mod, func, args, nargs);
+    return PyLong_AsLong(result);
+}
+
+char *python_callback_str(const char *abs_module_path, const char *mod,
+                          const char *func, char *args[], const int nargs)
+{
+    PyObject *result;
+    result = python_callback(abs_module_path, mod, func, args, nargs);
+    return PyUnicode_AsUTF8(result);
+}
+
+bool python_callback_bool(const char *abs_module_path, const char *mod,
+                          const char *func, char *args[], const int nargs)
+{
+    PyObject *result;
+    result = python_callback(abs_module_path, mod, func, args, nargs);
+    return (result == Py_True);
+}
+
+void python_args_init_cast_int(char *args[], int arg, int pos)
+{
+    args[pos]= malloc(sizeof(int));
+    sprintf(args[pos], "%d", arg);
+}
+
+void python_args_init_cast_long(char *args[], uint64_t arg, int pos)
+{
+    args[pos]= g_malloc(sizeof(uint64_t) * 2);
+    sprintf(args[pos], "%lx", arg);
+}
+
+void python_args_clean(char *args[], int nargs)
+{
+    for (int i = 0; i < nargs; i++) {
+        g_free(args[i]);
+    }
+}
-- 
2.14.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]