123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- #include <Python.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <strings.h>
- #include "pci.h"
- #include "debug.h"
- #include "pcilib.h"
- #include "py.h"
- #include "error.h"
- struct pcilib_py_s {
- PyObject *main_module;
- PyObject *global_dict;
- int py_initialized_inside; ///< Flag, shows that Py_Initialize has been called inside class
- };
- typedef struct pcilib_script_s {
- char* script_name;
- PyObject *py_script_module; /**< PyModule object, contains script enviroment */
- PyObject *dict;
- pcilib_access_mode_t mode;
-
- UT_hash_handle hh;
- } pcilib_script_s;
- struct pcilib_script_s *scripts = NULL;
- int pcilib_init_py(pcilib_t *ctx) {
- ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t));
- if (!ctx->py) return PCILIB_ERROR_MEMORY;
- if(!Py_IsInitialized())
- {
- Py_Initialize();
- 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;
- ctx->py->global_dict = PyModule_GetDict(ctx->py->main_module);
- if (!ctx->py->global_dict)
- return PCILIB_ERROR_FAILED;
-
-
- //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");
- 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");
- if(PyList_Append(path, PyString_FromString(model_path)) == -1)
- {
- pcilib_error("Cant set PCILIB_MODEL_DIR library path to python.");
- free(model_path);
- return PCILIB_ERROR_FAILED;
- }
- free(model_path);
- model_dir_added = 1;
- }
- return 0;
- }
- void pcilib_free_py(pcilib_t *ctx) {
-
- int py_initialized_inside = 0;
-
- if (ctx->py) {
- if(ctx->py->py_initialized_inside)
- py_initialized_inside = 1;
-
- // Dict and module references are borrowed
- free(ctx->py);
- ctx->py = NULL;
- }
-
- if(py_initialized_inside)
- Py_Finalize();
- }
- /*
- 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;
- }
- ]
- return 0;
- }
- */
- static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
- int i;
- int err = 0;
- pcilib_value_t val = {0};
- pcilib_register_value_t regval;
- char save;
- char *reg, *cur;
- size_t offset = 0;
- size_t size;
- char *src;
- char *dst;
- size_t max_repl = 2 + 2 * sizeof(pcilib_value_t); // the text representation of largest integer
- if (value) {
- err = pcilib_copy_value(ctx, &val, value);
- if (err) return NULL;
- err = pcilib_convert_value_type(ctx, &val, PCILIB_TYPE_STRING);
- if (err) return NULL;
- if (strlen(val.sval) > max_repl)
- max_repl = strlen(val.sval);
- }
- size = ((max_repl + 1) / 3 + 1) * strlen(codestr); // minimum register length is 3 symbols ($a + delimiter space), it is replaces with (max_repl+1) symbols
- src = strdup(codestr);
- dst = (char*)malloc(size); // allocating maximum required space
- if ((!src)||(!dst)) {
- if (src) free(src);
- if (dst) free(dst);
- pcilib_error("Failed to allocate memory for string formulas");
- return NULL;
- }
- cur = src;
- reg = strchr(src, '$');
- while (reg) {
- strcpy(dst + offset, cur);
- offset += reg - cur;
- // find the end of the register name
- reg++;
- if (*reg == '{') {
- reg++;
- for (i = 0; (reg[i])&&(reg[i] != '}'); i++);
- if (!reg[i]) {
- pcilib_error("Python formula (%s) contains unterminated variable reference", codestr);
- err = PCILIB_ERROR_INVALID_DATA;
- break;
- }
- } else {
- for (i = 0; isalnum(reg[i])||(reg[i] == '_'); i++);
- }
- save = reg[i];
- reg[i] = 0;
- // determine replacement value
- if (!strcasecmp(reg, "value")) {
- if (!value) {
- pcilib_error("Python formula (%s) relies on the value of register, but it is not provided", codestr);
- err = PCILIB_ERROR_INVALID_REQUEST;
- break;
- }
- strcpy(dst + offset, val.sval);
- } else {
- if (*reg == '/') {
- pcilib_value_t val = {0};
- err = pcilib_get_property(ctx, reg, &val);
- if (err) break;
- err = pcilib_convert_value_type(ctx, &val, PCILIB_TYPE_STRING);
- if (err) break;
- sprintf(dst + offset, "%s", val.sval);
- } else {
- err = pcilib_read_register(ctx, NULL, reg, ®val);
- if (err) break;
- sprintf(dst + offset, "0x%lx", regval);
- }
- }
- offset += strlen(dst + offset);
- if (save == '}') i++;
- else reg[i] = save;
- // Advance to the next register if any
- cur = reg + i;
- reg = strchr(cur, '$');
- }
- strcpy(dst + offset, cur);
- free(src);
- if (err) {
- free(dst);
- return NULL;
- }
- return dst;
- }
- int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
- 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);
- if (!obj) {
- pcilib_error("Failed to run the Python code: %s", code);
- return PCILIB_ERROR_FAILED;
- }
- 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));
- }
- void* pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val)
- {
- int err;
-
- switch(val->type)
- {
- case PCILIB_TYPE_INVALID:
- pcilib_error("Invalid register output type (PCILIB_TYPE_INVALID)");
- return NULL;
-
- case PCILIB_TYPE_STRING:
- pcilib_error("Invalid register output type (PCILIB_TYPE_STRING)");
- return NULL;
-
- case PCILIB_TYPE_LONG:
- {
- long ret;
- ret = pcilib_get_value_as_int(ctx, val, &err);
-
- if(err)
- {
- pcilib_error("Failed: pcilib_get_value_as_int (%i)", err);
- return NULL;
- }
- return (PyObject*)PyInt_FromLong((long) ret);
- }
-
- case PCILIB_TYPE_DOUBLE:
- {
- double ret;
- ret = pcilib_get_value_as_float(ctx, val, &err);
-
- if(err)
- {
- pcilib_error("Failed: pcilib_get_value_as_int (%i)", err);
- return NULL;
- }
- return (PyObject*)PyFloat_FromDouble((double) ret);
- }
-
- default:
- pcilib_error("Invalid register output type (unknown)");
- return NULL;
- }
- }
- int pcilib_set_value_from_pyobject(pcilib_t* ctx, void* pyObjVal, pcilib_value_t *val)
- {
- PyObject* pyVal = pyObjVal;
- int err;
-
- 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_static_string(ctx, val, PyString_AsString(pyVal));
- else
- {
- pcilib_error("Invalid input. Input type should be int, float or string.");
- return PCILIB_ERROR_NOTSUPPORTED;
- }
- if(err)
- return err;
-
- return 0;
- }
- int pcilib_py_init_script(pcilib_t *ctx, char* module_name, pcilib_access_mode_t *mode)
- {
- //extract module name from script name
- char* py_module_name = strtok(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( scripts, module_name, module);
- if(module)
- {
- pcilib_warning("Python module %s is already in hash. Skip init step", module_name);
- mode[0] = module->mode;
- return 0;
- }
-
- //Initialize python module
- if(!module_name)
- {
- pcilib_error("Invalid script name specified in XML property (NULL)");
- return PCILIB_ERROR_INVALID_DATA;
- }
-
- //import python script
- PyObject* py_script_module = PyImport_ImportModule(py_module_name);
-
- if(!py_script_module)
- {
- printf("Error in import python module: ");
- PyErr_Print();
- return PCILIB_ERROR_INVALID_DATA;
- }
- //Initializing pcipywrap module if script use it
- PyObject* dict = PyModule_GetDict(py_script_module);
- if(PyDict_Contains(dict, PyString_FromString("pcipywrap")))
- {
- PyObject* pcipywrap_module = PyDict_GetItemString(dict, "pcipywrap");
- if(!pcipywrap_module)
- {
- pcilib_error("Cant extract pcipywrap module from script dictionary");
- return PCILIB_ERROR_FAILED;
- }
-
- //setting pcilib_t instance
- PyObject_CallMethodObjArgs(pcipywrap_module,
- PyUnicode_FromString("set_pcilib"),
- PyByteArray_FromStringAndSize((const char*)&ctx, sizeof(pcilib_t*)),
- NULL);
- }
-
- //Success. Create struct and initialize values
- module = malloc(sizeof(pcilib_script_s));
- module->py_script_module = py_script_module;
- module->script_name = malloc(strlen(module_name));
- sprintf(module->script_name, "%s", module_name);
- module->dict = dict;
-
- //Setting correct mode
- mode[0] = 0;
- if(PyDict_Contains(dict, PyString_FromString("read_from_register")))
- mode[0] |= PCILIB_ACCESS_R;
- if(PyDict_Contains(dict, PyString_FromString("write_to_register")))
- mode[0] |= PCILIB_ACCESS_W;
-
- module->mode = mode[0];
- HASH_ADD_STR( scripts, script_name, module);
-
- return 0;
- }
- int pcilib_py_free_script(char* module_name)
- {
- pcilib_script_s *module;
- HASH_FIND_STR(scripts, module_name, module);
-
- if(!module)
- {
- //For some reason it will crash if uncomment. printf same warning is ok
- //pcilib_warning("Cant find Python module %s in hash. Seems it has already deleted.", module_name);
- return 0;
- }
-
- if(module->script_name)
- {
- free(module->script_name);
- module->script_name = NULL;
- }
-
- if(module->py_script_module)
- {
- //PyObject_Free(module->py_script_module);
- module->py_script_module = NULL;
- }
-
- HASH_DEL(scripts, module);
- free(module);
- return 0;
- }
- int pcilib_script_read(pcilib_t *ctx, char* module_name, pcilib_value_t *val)
- {
- pcilib_script_s *module;
- HASH_FIND_STR(scripts, module_name, module);
-
- if(!module)
- {
- pcilib_error("Failed to find script module (%s) in hash", module_name);
- return PCILIB_ERROR_NOTFOUND;
- }
-
- int err;
-
- PyObject *ret = PyObject_CallMethod(module->py_script_module, "read_from_register", "()");
- if (!ret)
- {
- printf("Python script error: ");
- PyErr_Print();
- return PCILIB_ERROR_FAILED;
- }
-
- err = pcilib_set_value_from_pyobject(ctx, ret, val);
-
- if(err)
- {
- pcilib_error("Failed to convert python script return value to internal type: %i", err);
- return err;
- }
- return 0;
- }
- int pcilib_script_write(pcilib_t *ctx, char* module_name, pcilib_value_t *val)
- {
- pcilib_script_s *module;
- HASH_FIND_STR(scripts, module_name, module);
-
- if(!module)
- {
- pcilib_error("Failed to find script module (%s) in hash", module_name);
- return PCILIB_ERROR_NOTFOUND;
- }
-
- PyObject *input = pcilib_get_value_as_pyobject(ctx, val);
- if(!input)
- {
- printf("Failed to convert input value to Python object");
- PyErr_Print();
- return PCILIB_ERROR_FAILED;
- }
-
- PyObject *ret = PyObject_CallMethodObjArgs(module->py_script_module,
- PyUnicode_FromString("write_to_register"),
- input,
- NULL);
- if (!ret)
- {
- printf("Python script error: ");
- PyErr_Print();
- return PCILIB_ERROR_FAILED;
- }
- return 0;
- }
|