|
@@ -1,10 +1,13 @@
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
-#include <Python.h>
|
|
|
-#endif
|
|
|
+#include "config.h"
|
|
|
+
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+# include <Python.h>
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
|
|
|
#include <stdio.h>
|
|
|
#include <string.h>
|
|
|
#include <strings.h>
|
|
|
+#include <alloca.h>
|
|
|
|
|
|
#include "pci.h"
|
|
|
#include "debug.h"
|
|
@@ -12,150 +15,362 @@
|
|
|
#include "py.h"
|
|
|
#include "error.h"
|
|
|
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
-typedef struct pcilib_script_s {
|
|
|
- const char* name;
|
|
|
- PyObject *module; /**< PyModule object, contains script enviroment */
|
|
|
- UT_hash_handle hh;
|
|
|
-} pcilib_script_s;
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+typedef struct pcilib_script_s pcilib_script_t;
|
|
|
+
|
|
|
+struct pcilib_script_s {
|
|
|
+ const char *name; /**< Script name */
|
|
|
+ PyObject *module; /**< PyModule object, contains script enviroment */
|
|
|
+ UT_hash_handle hh; /**< hash */
|
|
|
+};
|
|
|
|
|
|
struct pcilib_py_s {
|
|
|
- PyObject *main_module;
|
|
|
- PyObject *global_dict;
|
|
|
- PyObject *pcilib_pywrap;
|
|
|
- int py_initialized_inside; ///< Flag, shows that Py_Initialize has been called inside class
|
|
|
- struct pcilib_script_s *scripts;
|
|
|
+ int finalyze; /**< Indicates, that we are initialized from wrapper and should not destroy Python resources in destructor */
|
|
|
+ PyObject *main_module; /**< Main interpreter */
|
|
|
+ PyObject *global_dict; /**< Dictionary of main interpreter */
|
|
|
+ PyObject *pcilib_pywrap; /**< pcilib wrapper module */
|
|
|
+ pcilib_script_t *script_hash; /**< Hash with loaded scripts */
|
|
|
};
|
|
|
-#endif
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
+
|
|
|
+void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flags, pcilib_log_priority_t prio, const char *msg, ...) {
|
|
|
+ va_list va;
|
|
|
+ const char *type = NULL;
|
|
|
+ const char *val = NULL;
|
|
|
+
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ PyGILState_STATE gstate;
|
|
|
+ PyObject *pytype = NULL;
|
|
|
+ PyObject *pyval = NULL;
|
|
|
+ PyObject *pytraceback = NULL;
|
|
|
+
|
|
|
+
|
|
|
+ gstate = PyGILState_Ensure();
|
|
|
+ if (PyErr_Occurred()) {
|
|
|
+ PyErr_Fetch(&pytype, &pyval, &pytraceback);
|
|
|
+ type = PyString_AsString(pytype);
|
|
|
+ val = PyString_AsString(pyval);
|
|
|
+ }
|
|
|
+ PyGILState_Release(gstate);
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
+
|
|
|
+ va_start(va, msg);
|
|
|
+ if (type) {
|
|
|
+ char *str;
|
|
|
+ size_t len = 32;
|
|
|
+
|
|
|
+ if (msg) len += strlen(msg);
|
|
|
+ if (type) len += strlen(type);
|
|
|
+ if (val) len += strlen(val);
|
|
|
+
|
|
|
+ str = alloca(len * sizeof(char));
|
|
|
+ if (str) {
|
|
|
+ if (msg&&val)
|
|
|
+ sprintf(str, "%s <%s: %s>", msg, type, val);
|
|
|
+ else if (msg)
|
|
|
+ sprintf(str, "%s <%s>", msg, type);
|
|
|
+ else if (val)
|
|
|
+ sprintf(str, "Python error %s: %s", type, val);
|
|
|
+ else
|
|
|
+ sprintf(str, "Python error %s", type);
|
|
|
+
|
|
|
+ pcilib_log_vmessage(file, line, flags, prio, str, va);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ pcilib_log_vmessage(file, line, flags, prio, msg, va);
|
|
|
+ }
|
|
|
+ va_end(va);
|
|
|
+
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ if (pytype) Py_XDECREF(pytype);
|
|
|
+ if (pyval) Py_XDECREF(pyval);
|
|
|
+ if (pytraceback) Py_XDECREF(pytraceback);
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
int pcilib_init_py(pcilib_t *ctx) {
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t));
|
|
|
if (!ctx->py) return PCILIB_ERROR_MEMORY;
|
|
|
|
|
|
- if(!Py_IsInitialized())
|
|
|
- {
|
|
|
+ memset(ctx->py, 0, sizeof(pcilib_py_t));
|
|
|
+
|
|
|
+ if(Py_IsInitialized())
|
|
|
+ ctx->py->finalyze = 0;
|
|
|
+ else {
|
|
|
Py_Initialize();
|
|
|
|
|
|
- //Since python is being initializing from c programm, it needs
|
|
|
- //to initialize threads to works properly with c threads
|
|
|
+ // Since python is being initializing from c programm, it needs to initialize threads to work properly with c threads
|
|
|
PyEval_InitThreads();
|
|
|
PyEval_ReleaseLock();
|
|
|
-
|
|
|
- ctx->py->py_initialized_inside = 1;
|
|
|
- }
|
|
|
- else
|
|
|
- ctx->py->py_initialized_inside = 0;
|
|
|
+ }
|
|
|
|
|
|
ctx->py->main_module = PyImport_AddModule("__parser__");
|
|
|
- if (!ctx->py->main_module)
|
|
|
- return PCILIB_ERROR_FAILED;
|
|
|
+ if (!ctx->py->main_module) {
|
|
|
+ pcilib_python_error("Error importing python parser");
|
|
|
+ return PCILIB_ERROR_FAILED;
|
|
|
+ }
|
|
|
|
|
|
ctx->py->global_dict = PyModule_GetDict(ctx->py->main_module);
|
|
|
- if (!ctx->py->global_dict)
|
|
|
- return PCILIB_ERROR_FAILED;
|
|
|
-
|
|
|
-
|
|
|
+ if (!ctx->py->global_dict) {
|
|
|
+ pcilib_python_error("Error locating global python dictionary");
|
|
|
+ return PCILIB_ERROR_FAILED;
|
|
|
+ }
|
|
|
|
|
|
- PyObject* py_script_module = PyImport_ImportModule("pcipywrap");
|
|
|
- if(!py_script_module)
|
|
|
- {
|
|
|
- printf("Error in import python module: ");
|
|
|
- PyErr_Print();
|
|
|
- return PCILIB_ERROR_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- PyObject* mod_name = PyString_FromString("Pcipywrap");
|
|
|
- PyObject* py_ctx = PyCObject_FromVoidPtr(ctx, NULL);
|
|
|
- ctx->py->pcilib_pywrap = PyObject_CallMethodObjArgs(py_script_module,
|
|
|
- mod_name,
|
|
|
- py_ctx,
|
|
|
- NULL);
|
|
|
- Py_XDECREF(mod_name);
|
|
|
- Py_XDECREF(py_ctx);
|
|
|
+ PyObject *pywrap = PyImport_ImportModule("pcipywrap");
|
|
|
+ if (!pywrap) {
|
|
|
+ pcilib_python_error("Error importing pcilib python wrapper");
|
|
|
+ return PCILIB_ERROR_FAILED;
|
|
|
+ }
|
|
|
|
|
|
- if(!ctx->py->pcilib_pywrap)
|
|
|
- {
|
|
|
- printf("Error in import python module: ");
|
|
|
- PyErr_Print();
|
|
|
- return PCILIB_ERROR_FAILED;
|
|
|
- }
|
|
|
+ PyObject *mod_name = PyString_FromString("Pcipywrap");
|
|
|
+ PyObject *ctx_py_ptr = PyCObject_FromVoidPtr(ctx, NULL);
|
|
|
+ ctx->py->pcilib_pywrap = PyObject_CallMethodObjArgs(pywrap, mod_name, ctx_py_ptr, NULL);
|
|
|
+ Py_DECREF(ctx_py_ptr);
|
|
|
+ Py_DECREF(mod_name);
|
|
|
|
|
|
- ctx->py->scripts = NULL;
|
|
|
-#endif
|
|
|
+ if (!ctx->py->pcilib_pywrap) {
|
|
|
+ pcilib_python_error("Error initializing python wrapper");
|
|
|
+ return PCILIB_ERROR_FAILED;
|
|
|
+ }
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int pcilib_py_add_script_dir(pcilib_t *ctx)
|
|
|
-{
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
- //create path string, where the model scripts should be
|
|
|
- static int model_dir_added = 0;
|
|
|
- if(!model_dir_added)
|
|
|
- {
|
|
|
- char* model_dir = getenv("PCILIB_MODEL_DIR");
|
|
|
- if(!model_dir)
|
|
|
- {
|
|
|
- pcilib_error("Enviroment variable PCILIB_MODEL_DIR not set.");
|
|
|
- return PCILIB_ERROR_NOTINITIALIZED;
|
|
|
- }
|
|
|
- char* model_path = malloc(strlen(model_dir) + strlen(ctx->model) + 2);
|
|
|
- if (!model_path) return PCILIB_ERROR_MEMORY;
|
|
|
- sprintf(model_path, "%s/%s", model_dir, ctx->model);
|
|
|
- //add path to python
|
|
|
- PyObject* path = PySys_GetObject("path");
|
|
|
- PyObject* py_model_path = PyString_FromString(model_path);
|
|
|
- if(PyList_Append(path, py_model_path) == -1)
|
|
|
- {
|
|
|
- Py_XDECREF(py_model_path);
|
|
|
- pcilib_error("Cant set PCILIB_MODEL_DIR library path to python.");
|
|
|
- free(model_path);
|
|
|
- return PCILIB_ERROR_FAILED;
|
|
|
- }
|
|
|
- Py_XDECREF(py_model_path);
|
|
|
- free(model_path);
|
|
|
- model_dir_added = 1;
|
|
|
- }
|
|
|
-#endif
|
|
|
- return 0;
|
|
|
+int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) {
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ PyObject* pypath;
|
|
|
+ char *script_dir;
|
|
|
+
|
|
|
+ const char *model_dir = getenv("PCILIB_MODEL_DIR");
|
|
|
+ if (!model_dir) model_dir = PCILIB_MODEL_DIR;
|
|
|
+
|
|
|
+ if (!dir) dir = ctx->model;
|
|
|
+
|
|
|
+ if (*dir == '/') {
|
|
|
+ script_dir = (char*)dir;
|
|
|
+ } else {
|
|
|
+ script_dir = alloca(strlen(model_dir) + strlen(dir) + 2);
|
|
|
+ if (!script_dir) return PCILIB_ERROR_MEMORY;
|
|
|
+ sprintf(script_dir, "%s/%s", model_dir, dir);
|
|
|
+ }
|
|
|
+
|
|
|
+ pypath = PySys_GetObject("path");
|
|
|
+ if (!pypath) {
|
|
|
+ pcilib_python_error("Can't get python path");
|
|
|
+ return PCILIB_ERROR_FAILED;
|
|
|
+ }
|
|
|
+
|
|
|
+ PyObject* new_path = PyString_FromString(script_dir);
|
|
|
+
|
|
|
+ //Check if sys.path already contains our path
|
|
|
+ PyObject* dict = PyDict_New();
|
|
|
+ PyObject* cur_py = PyString_FromString("cur");
|
|
|
+ PyObject* path_py = PyString_FromString("path");
|
|
|
+ PyDict_SetItem(dict, cur_py, new_path);
|
|
|
+ PyDict_SetItem(dict, path_py, pypath);
|
|
|
+ Py_DECREF(cur_py);
|
|
|
+ Py_DECREF(path_py);
|
|
|
+
|
|
|
+ PyObject* pyret = PyRun_String("cur in path", Py_eval_input,
|
|
|
+ ctx->py->global_dict,
|
|
|
+ dict);
|
|
|
+ Py_DECREF(dict);
|
|
|
+
|
|
|
+ if(pyret == Py_False) {
|
|
|
+ if(PyList_Append(pypath, new_path) == -1) {
|
|
|
+ pcilib_python_error("Can't add directory (%s) to python path", script_dir);
|
|
|
+ return PCILIB_ERROR_FAILED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(pyret == Py_True)
|
|
|
+ {
|
|
|
+ printf("1\n");
|
|
|
+ Py_DECREF(new_path);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
void pcilib_free_py(pcilib_t *ctx) {
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
- int py_initialized_inside = 0;
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ int finalyze = 0;
|
|
|
|
|
|
- if (ctx->py) {
|
|
|
- if(ctx->py->py_initialized_inside)
|
|
|
- py_initialized_inside = 1;
|
|
|
-
|
|
|
- // Dict and module references are borrowed
|
|
|
- Py_XDECREF(ctx->py->pcilib_pywrap);
|
|
|
- free(ctx->py);
|
|
|
- ctx->py = NULL;
|
|
|
- }
|
|
|
+ if (ctx->py) {
|
|
|
+
|
|
|
+ if(ctx->py->finalyze) finalyze = 1;
|
|
|
+ if (ctx->py->script_hash) {
|
|
|
+ pcilib_script_t *script, *script_tmp;
|
|
|
+
|
|
|
+ HASH_ITER(hh, ctx->py->script_hash, script, script_tmp) {
|
|
|
+ Py_DECREF(script->module);
|
|
|
+
|
|
|
+ HASH_DEL(ctx->py->script_hash, script);
|
|
|
+ free(script);
|
|
|
+ }
|
|
|
+ ctx->py->script_hash = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ Py_DECREF(ctx->py->pcilib_pywrap);
|
|
|
+
|
|
|
+ free(ctx->py);
|
|
|
+ ctx->py = NULL;
|
|
|
+ }
|
|
|
|
|
|
- if(py_initialized_inside)
|
|
|
- Py_Finalize();
|
|
|
-#endif
|
|
|
+ if (finalyze)
|
|
|
+ Py_Finalize();
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
-static int pcilib_py_realloc_string(pcilib_t *ctx, size_t required, size_t *size, char **str) {
|
|
|
- char *ptr;
|
|
|
- size_t cur = *size;
|
|
|
-
|
|
|
- if ((required + 1) > cur) {
|
|
|
- while (cur < required) cur *= 2;
|
|
|
- ptr = (char*)realloc(*str, cur);
|
|
|
- if (!ptr) return PCILIB_ERROR_MEMORY;
|
|
|
- *size = cur;
|
|
|
- *str = ptr;
|
|
|
- }
|
|
|
- ]
|
|
|
+int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) {
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ PyObject* pymodule;
|
|
|
+ pcilib_script_t *module = NULL;
|
|
|
+
|
|
|
+
|
|
|
+ char *module_name = strdupa(script_name);
|
|
|
+ if (!module_name) return PCILIB_ERROR_MEMORY;
|
|
|
+
|
|
|
+ char *py = strrchr(module_name, '.');
|
|
|
+ if ((!py)||(strcasecmp(py, ".py"))) {
|
|
|
+ pcilib_error("Invalid script name (%s) is specified", script_name);
|
|
|
+ return PCILIB_ERROR_INVALID_ARGUMENT;
|
|
|
+ }
|
|
|
+ *py = 0;
|
|
|
+
|
|
|
+ HASH_FIND_STR(ctx->py->script_hash, script_name, module);
|
|
|
+ if (module) return 0;
|
|
|
+
|
|
|
+ pymodule = PyImport_ImportModule(module_name);
|
|
|
+ if (!pymodule) {
|
|
|
+ pcilib_python_error("Error importing script (%s)", script_name);
|
|
|
+ return PCILIB_ERROR_FAILED;
|
|
|
+ }
|
|
|
+
|
|
|
+ module = (pcilib_script_t*)malloc(sizeof(pcilib_script_t));
|
|
|
+ if (!module) return PCILIB_ERROR_MEMORY;
|
|
|
+
|
|
|
+ module->module = pymodule;
|
|
|
+ module->name = script_name;
|
|
|
+ HASH_ADD_KEYPTR(hh, ctx->py->script_hash, module->name, strlen(module->name), module);
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char *script_name, pcilib_access_mode_t *mode_ret) {
|
|
|
+ pcilib_access_mode_t mode = 0;
|
|
|
+
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ PyObject *dict;
|
|
|
+ PyObject *pystr;
|
|
|
+ pcilib_script_t *module;
|
|
|
+
|
|
|
+ HASH_FIND_STR(ctx->py->script_hash, script_name, module);
|
|
|
+
|
|
|
+ if(!module) {
|
|
|
+ pcilib_error("Script (%s) is not loaded yet", script_name);
|
|
|
+ return PCILIB_ERROR_NOTFOUND;
|
|
|
+ }
|
|
|
+
|
|
|
+ dict = PyModule_GetDict(module->module);
|
|
|
+ if (!dict) {
|
|
|
+ pcilib_python_error("Error getting dictionary for script (%s)", script_name);
|
|
|
+ return PCILIB_ERROR_FAILED;
|
|
|
+ }
|
|
|
+
|
|
|
+ pystr = PyString_FromString("read_from_register");
|
|
|
+ if (pystr) {
|
|
|
+ if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_R;
|
|
|
+ Py_XDECREF(pystr);
|
|
|
+ }
|
|
|
+
|
|
|
+ pystr = PyString_FromString("write_to_register");
|
|
|
+ if (pystr) {
|
|
|
+ if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_W;
|
|
|
+ Py_XDECREF(pystr);
|
|
|
+ }
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
+
|
|
|
+ if (mode_ret) *mode_ret = mode;
|
|
|
return 0;
|
|
|
}
|
|
|
-*/
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
+
|
|
|
+pcilib_py_object *pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val, int *ret) {
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ int err = 0;
|
|
|
+ PyObject *res = NULL;
|
|
|
+ PyGILState_STATE gstate;
|
|
|
+
|
|
|
+ long ival;
|
|
|
+ double fval;
|
|
|
+
|
|
|
+ gstate = PyGILState_Ensure();
|
|
|
+ switch(val->type) {
|
|
|
+ case PCILIB_TYPE_LONG:
|
|
|
+ ival = pcilib_get_value_as_int(ctx, val, &err);
|
|
|
+ if (!err) res = (PyObject*)PyInt_FromLong(ival);
|
|
|
+ break;
|
|
|
+ case PCILIB_TYPE_DOUBLE:
|
|
|
+ fval = pcilib_get_value_as_float(ctx, val, &err);
|
|
|
+ if (!err) res = (PyObject*)PyFloat_FromDouble(fval);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ PyGILState_Release(gstate);
|
|
|
+ pcilib_error("Can't convert pcilib value of type (%lu) to PyObject", val->type);
|
|
|
+ if (ret) *ret = PCILIB_ERROR_NOTSUPPORTED;
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ PyGILState_Release(gstate);
|
|
|
+
|
|
|
+ if (err) {
|
|
|
+ if (ret) *ret = err;
|
|
|
+ return NULL;
|
|
|
+ } else if (!res) {
|
|
|
+ if (ret) *ret = PCILIB_ERROR_MEMORY;
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ret) *ret = 0;
|
|
|
+ return res;
|
|
|
+#else /* HAVE_PYTHON */
|
|
|
+ pcilib_error("Python is not supported");
|
|
|
+ return NULL;
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
+}
|
|
|
+
|
|
|
+int pcilib_set_value_from_pyobject(pcilib_t* ctx, pcilib_value_t *val, pcilib_py_object *pval) {
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ int err = 0;
|
|
|
+ PyObject *pyval = (PyObject*)pval;
|
|
|
+ PyGILState_STATE gstate;
|
|
|
+
|
|
|
+ gstate = PyGILState_Ensure();
|
|
|
+ if (PyInt_Check(pyval)) {
|
|
|
+ err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyval));
|
|
|
+ } else if (PyFloat_Check(pyval)) {
|
|
|
+ err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(pyval));
|
|
|
+ } else if (PyString_Check(pyval)) {
|
|
|
+ err = pcilib_set_value_from_string(ctx, val, PyString_AsString(pyval));
|
|
|
+ } else {
|
|
|
+ PyGILState_Release(gstate);
|
|
|
+ pcilib_error("Can't convert PyObject to polymorphic pcilib value");
|
|
|
+ return PCILIB_ERROR_NOTSUPPORTED;
|
|
|
+ }
|
|
|
+ PyGILState_Release(gstate);
|
|
|
+
|
|
|
+ return err;
|
|
|
+#else /* HAVE_PYTHON */
|
|
|
+ pcilib_error("Python is not supported");
|
|
|
+ return PCILIB_ERROR_NOTSUPPORTED;
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
|
|
|
int i;
|
|
|
int err = 0;
|
|
@@ -261,23 +476,28 @@ static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_v
|
|
|
|
|
|
return dst;
|
|
|
}
|
|
|
-#endif
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
|
|
|
int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ int err;
|
|
|
+
|
|
|
PyGILState_STATE gstate;
|
|
|
char *code;
|
|
|
PyObject* obj;
|
|
|
|
|
|
+
|
|
|
code = pcilib_py_parse_string(ctx, codestr, value);
|
|
|
if (!code) {
|
|
|
pcilib_error("Failed to parse registers in the code: %s", codestr);
|
|
|
return PCILIB_ERROR_FAILED;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
gstate = PyGILState_Ensure();
|
|
|
obj = PyRun_String(code, Py_eval_input, ctx->py->global_dict, ctx->py->global_dict);
|
|
|
PyGILState_Release(gstate);
|
|
|
+
|
|
|
+ free(code);
|
|
|
|
|
|
if (!obj) {
|
|
|
pcilib_error("Failed to run the Python code: %s", code);
|
|
@@ -285,253 +505,64 @@ int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *va
|
|
|
}
|
|
|
|
|
|
pcilib_debug(VIEWS, "Evaluating a Python string \'%s\' to %lf=\'%s\'", codestr, PyFloat_AsDouble(obj), code);
|
|
|
- return pcilib_set_value_from_float(ctx, value, PyFloat_AsDouble(obj));
|
|
|
-#else
|
|
|
- pcilib_error("Current build not support python.");
|
|
|
+ err = pcilib_set_value_from_float(ctx, value, PyFloat_AsDouble(obj));
|
|
|
+ Py_DECREF(obj);
|
|
|
+
|
|
|
+ return err;
|
|
|
+#else /* HAVE_PYTHON */
|
|
|
+ pcilib_error("Current build not support python.");
|
|
|
return PCILIB_ERROR_NOTAVAILABLE;
|
|
|
-#endif
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
}
|
|
|
|
|
|
-pcilib_py_object* pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val, int *ret)
|
|
|
-{
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
- int err;
|
|
|
-
|
|
|
- switch(val->type)
|
|
|
- {
|
|
|
- case PCILIB_TYPE_INVALID:
|
|
|
- pcilib_error("Invalid register output type (PCILIB_TYPE_INVALID)");
|
|
|
- if (ret) *ret = PCILIB_ERROR_NOTSUPPORTED;
|
|
|
- return NULL;
|
|
|
-
|
|
|
- case PCILIB_TYPE_STRING:
|
|
|
- pcilib_error("Invalid register output type (PCILIB_TYPE_STRING)");
|
|
|
- if (ret) *ret = PCILIB_ERROR_NOTSUPPORTED;
|
|
|
- return NULL;
|
|
|
-
|
|
|
- case PCILIB_TYPE_LONG:
|
|
|
- {
|
|
|
- long ret_val;
|
|
|
- ret_val = pcilib_get_value_as_int(ctx, val, &err);
|
|
|
-
|
|
|
- if(err)
|
|
|
- {
|
|
|
- if (ret) *ret = err;
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (ret) *ret = 0;
|
|
|
- return (PyObject*)PyInt_FromLong((long) ret_val);
|
|
|
- }
|
|
|
-
|
|
|
- case PCILIB_TYPE_DOUBLE:
|
|
|
- {
|
|
|
- double ret_val;
|
|
|
- ret_val = pcilib_get_value_as_float(ctx, val, &err);
|
|
|
-
|
|
|
- if(err)
|
|
|
- {
|
|
|
- if (ret) *ret = err;
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (ret) *ret = 0;
|
|
|
- return (PyObject*)PyFloat_FromDouble((double) ret_val);
|
|
|
- }
|
|
|
-
|
|
|
- default:
|
|
|
- if (ret) *ret = PCILIB_ERROR_NOTSUPPORTED;
|
|
|
- pcilib_error("Invalid register output type (unknown)");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-#else
|
|
|
- pcilib_error("Current build not support python.");
|
|
|
- if (ret) *ret = PCILIB_ERROR_NOTAVAILABLE;
|
|
|
- return NULL;
|
|
|
-#endif
|
|
|
-}
|
|
|
+int pcilib_py_eval_func(pcilib_t *ctx, const char *script_name, const char *func_name, pcilib_value_t *val) {
|
|
|
+#ifdef HAVE_PYTHON
|
|
|
+ int err = 0;
|
|
|
+ PyObject *pyfunc;
|
|
|
+ PyObject *pyval = NULL, *pyret;
|
|
|
+ pcilib_script_t *module = NULL;
|
|
|
|
|
|
-int pcilib_set_value_from_pyobject(pcilib_t* ctx, pcilib_value_t *val, pcilib_py_object* pyObjVal)
|
|
|
-{
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
- PyObject* pyVal = pyObjVal;
|
|
|
- int err;
|
|
|
-
|
|
|
- PyGILState_STATE gstate = PyGILState_Ensure();
|
|
|
- if(PyInt_Check(pyVal))
|
|
|
- {
|
|
|
- err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyVal));
|
|
|
+ HASH_FIND_STR(ctx->py->script_hash, script_name, module);
|
|
|
+
|
|
|
+ if (!module) {
|
|
|
+ pcilib_error("Script (%s) is not loaded", script_name);
|
|
|
+ return PCILIB_ERROR_NOTFOUND;
|
|
|
}
|
|
|
- else
|
|
|
- if(PyFloat_Check(pyVal))
|
|
|
- err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(pyVal));
|
|
|
- else
|
|
|
- if(PyString_Check(pyVal))
|
|
|
- err = pcilib_set_value_from_static_string(ctx, val, PyString_AsString(pyVal));
|
|
|
- else
|
|
|
- {
|
|
|
- PyGILState_Release(gstate);
|
|
|
- pcilib_error("Invalid input. Input type should be int, float or string.");
|
|
|
- return PCILIB_ERROR_NOTSUPPORTED;
|
|
|
- }
|
|
|
- PyGILState_Release(gstate);
|
|
|
- if(err)
|
|
|
- return err;
|
|
|
-
|
|
|
- return 0;
|
|
|
-#else
|
|
|
- pcilib_error("Current build not support python.");
|
|
|
- return PCILIB_ERROR_NOTAVAILABLE;
|
|
|
-#endif
|
|
|
-}
|
|
|
|
|
|
-int pcilib_py_init_script(pcilib_t *ctx, const char* module_name)
|
|
|
-{
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
- //extract module name from script name
|
|
|
- char* py_module_name = strdup(module_name);
|
|
|
- py_module_name = strtok(py_module_name, ".");
|
|
|
- if(!py_module_name)
|
|
|
- {
|
|
|
- pcilib_error("Invalid script name specified in XML property (%s)."
|
|
|
- " Seems like name doesnt contains extension", module_name);
|
|
|
- return PCILIB_ERROR_INVALID_DATA;
|
|
|
- }
|
|
|
-
|
|
|
- pcilib_script_s* module = NULL;
|
|
|
- HASH_FIND_STR( ctx->py->scripts, module_name, module);
|
|
|
- if(module)
|
|
|
- {
|
|
|
- pcilib_warning("Python module %s is already in hash. Skip init step", module_name);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- //import python script
|
|
|
- PyObject* py_script_module = PyImport_ImportModule(py_module_name);
|
|
|
- if(!py_script_module)
|
|
|
- {
|
|
|
- printf("Error in import python module: ");
|
|
|
- PyErr_Print();
|
|
|
- free(py_module_name);
|
|
|
- return PCILIB_ERROR_INVALID_DATA;
|
|
|
- }
|
|
|
- free(py_module_name);
|
|
|
-
|
|
|
- //Success. Create struct and initialize values
|
|
|
- module = malloc(sizeof(pcilib_script_s));
|
|
|
- if (!module)
|
|
|
- return PCILIB_ERROR_MEMORY;
|
|
|
- module->module = py_script_module;
|
|
|
- module->name = module_name;
|
|
|
- HASH_ADD_STR( ctx->py->scripts, name, module);
|
|
|
-#endif
|
|
|
- return 0;
|
|
|
-}
|
|
|
+ if (val) {
|
|
|
+ pyval = pcilib_get_value_as_pyobject(ctx, val, &err);
|
|
|
+ if (err) return err;
|
|
|
+ }
|
|
|
|
|
|
-int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char* module_name,
|
|
|
-pcilib_access_mode_t *mode)
|
|
|
-{
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
- pcilib_script_s *module;
|
|
|
-
|
|
|
- HASH_FIND_STR(ctx->py->scripts, module_name, module);
|
|
|
- if(!module)
|
|
|
- {
|
|
|
- pcilib_error("Failed to find script module (%s) in hash", module_name);
|
|
|
- return PCILIB_ERROR_NOTFOUND;
|
|
|
- }
|
|
|
-
|
|
|
- PyObject* dict = PyModule_GetDict(module->module);
|
|
|
- //Setting correct mode
|
|
|
- mode[0] = 0;
|
|
|
- PyObject* py_read_from_register = PyString_FromString("read_from_register");
|
|
|
- if(PyDict_Contains(dict, py_read_from_register))
|
|
|
- mode[0] |= PCILIB_ACCESS_R;
|
|
|
- Py_XDECREF(py_read_from_register);
|
|
|
- PyObject* py_write_to_register = PyString_FromString("write_to_register");
|
|
|
- if(PyDict_Contains(dict, py_write_to_register))
|
|
|
- mode[0] |= PCILIB_ACCESS_W;
|
|
|
- Py_XDECREF(py_write_to_register);
|
|
|
- return 0;
|
|
|
-#else
|
|
|
- mode[0] = PCILIB_ACCESS_RW;
|
|
|
- return 0;
|
|
|
-#endif
|
|
|
-}
|
|
|
+ PyGILState_STATE gstate = PyGILState_Ensure();
|
|
|
|
|
|
-int pcilib_py_free_script(pcilib_t *ctx, const char* module_name)
|
|
|
-{
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
- pcilib_script_s *module;
|
|
|
- HASH_FIND_STR(ctx->py->scripts, module_name, module);
|
|
|
-
|
|
|
- if(!module)
|
|
|
- {
|
|
|
- pcilib_warning("Cant find Python module %s in hash. Seems it has already deleted.", module_name);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- if(module->module)
|
|
|
- {
|
|
|
- module->module = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- HASH_DEL(ctx->py->scripts, module);
|
|
|
- free(module);
|
|
|
-#endif
|
|
|
- return 0;
|
|
|
-}
|
|
|
+ pyfunc = PyUnicode_FromString(func_name);
|
|
|
+ if (!pyfunc) {
|
|
|
+ if (pyval) Py_XDECREF(pyval);
|
|
|
+ PyGILState_Release(gstate);
|
|
|
+ return PCILIB_ERROR_MEMORY;
|
|
|
+ }
|
|
|
|
|
|
-int pcilib_script_run_func(pcilib_t *ctx, const char* module_name,
|
|
|
- const char* func_name, pcilib_value_t *val)
|
|
|
-{
|
|
|
-#ifdef BUILD_PYTHON_MODULES
|
|
|
- int err;
|
|
|
- pcilib_script_s *module;
|
|
|
- HASH_FIND_STR(ctx->py->scripts, module_name, module);
|
|
|
- if(!module)
|
|
|
- {
|
|
|
- pcilib_error("Failed to find script module (%s) in hash", module_name);
|
|
|
- return PCILIB_ERROR_NOTFOUND;
|
|
|
- }
|
|
|
-
|
|
|
- PyGILState_STATE gstate = PyGILState_Ensure();
|
|
|
- PyObject *input = pcilib_get_value_as_pyobject(ctx, val, &err);
|
|
|
- if(err)
|
|
|
- return err;
|
|
|
-
|
|
|
- PyObject *py_func_name = PyUnicode_FromString(func_name);
|
|
|
- PyObject *ret = PyObject_CallMethodObjArgs(module->module,
|
|
|
- py_func_name,
|
|
|
- ctx->py->pcilib_pywrap,
|
|
|
- input,
|
|
|
- NULL);
|
|
|
-
|
|
|
- Py_XDECREF(py_func_name);
|
|
|
- Py_XDECREF(input);
|
|
|
- PyGILState_Release(gstate);
|
|
|
+ pyret = PyObject_CallMethodObjArgs(module->module, pyfunc, ctx->py->pcilib_pywrap, pyval, NULL);
|
|
|
+
|
|
|
+ Py_XDECREF(pyfunc);
|
|
|
+ Py_XDECREF(pyval);
|
|
|
|
|
|
- if (!ret)
|
|
|
- {
|
|
|
- printf("Python script error: ");
|
|
|
- PyErr_Print();
|
|
|
+ if (!pyret) {
|
|
|
+ PyGILState_Release(gstate);
|
|
|
+ pcilib_python_error("Error executing function (%s) of python script (%s)", func_name, script_name);
|
|
|
return PCILIB_ERROR_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- if(ret != Py_None)
|
|
|
- {
|
|
|
- err = pcilib_set_value_from_pyobject(ctx, val, ret);
|
|
|
- Py_XDECREF(ret);
|
|
|
-
|
|
|
- if(err)
|
|
|
- {
|
|
|
- pcilib_error("Failed to convert python script return value to internal type: %i", err);
|
|
|
- return err;
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
-#else
|
|
|
- pcilib_error("Current build not support python.");
|
|
|
- return PCILIB_ERROR_NOTAVAILABLE;
|
|
|
-#endif
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((val)&&(pyret != Py_None))
|
|
|
+ err = pcilib_set_value_from_pyobject(ctx, val, pyret);
|
|
|
+
|
|
|
+ Py_XDECREF(pyret);
|
|
|
+ PyGILState_Release(gstate);
|
|
|
+
|
|
|
+ return err;
|
|
|
+#else /* HAVE_PYTHON */
|
|
|
+ pcilib_error("Python is not supported");
|
|
|
+ return PCILIB_ERROR_NOTSUPPORTED;
|
|
|
+#endif /* HAVE_PYTHON */
|
|
|
}
|