py.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. #include <Python.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <strings.h>
  6. #include "pci.h"
  7. #include "debug.h"
  8. #include "pcilib.h"
  9. #include "py.h"
  10. #include "error.h"
  11. struct pcilib_py_s {
  12. PyObject *main_module;
  13. PyObject *global_dict;
  14. int py_initialized_inside; ///< Flag, shows that Py_Initialize has been called inside class
  15. };
  16. typedef struct pcilib_script_s {
  17. char* script_name;
  18. PyObject *py_script_module; /**< PyModule object, contains script enviroment */
  19. PyObject *dict;
  20. pcilib_access_mode_t mode;
  21. UT_hash_handle hh;
  22. } pcilib_script_s;
  23. struct pcilib_script_s *scripts = NULL;
  24. int pcilib_init_py(pcilib_t *ctx) {
  25. ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t));
  26. if (!ctx->py) return PCILIB_ERROR_MEMORY;
  27. if(!Py_IsInitialized())
  28. {
  29. Py_Initialize();
  30. ctx->py->py_initialized_inside = 1;
  31. }
  32. else
  33. ctx->py->py_initialized_inside = 0;
  34. ctx->py->main_module = PyImport_AddModule("__parser__");
  35. if (!ctx->py->main_module)
  36. return PCILIB_ERROR_FAILED;
  37. ctx->py->global_dict = PyModule_GetDict(ctx->py->main_module);
  38. if (!ctx->py->global_dict)
  39. return PCILIB_ERROR_FAILED;
  40. //create path string, where the model scripts should be
  41. static int model_dir_added = 0;
  42. if(!model_dir_added)
  43. {
  44. char* model_dir = getenv("PCILIB_MODEL_DIR");
  45. char* model_path = malloc(strlen(model_dir) + strlen(ctx->model) + 2);
  46. if (!model_path) return PCILIB_ERROR_MEMORY;
  47. sprintf(model_path, "%s/%s", model_dir, ctx->model);
  48. //add path to python
  49. PyObject* path = PySys_GetObject("path");
  50. if(PyList_Append(path, PyString_FromString(model_path)) == -1)
  51. {
  52. pcilib_error("Cant set PCILIB_MODEL_DIR library path to python.");
  53. free(model_path);
  54. return PCILIB_ERROR_FAILED;
  55. }
  56. free(model_path);
  57. model_dir_added = 1;
  58. }
  59. return 0;
  60. }
  61. void pcilib_free_py(pcilib_t *ctx) {
  62. int py_initialized_inside = 0;
  63. if (ctx->py) {
  64. if(ctx->py->py_initialized_inside)
  65. py_initialized_inside = 1;
  66. // Dict and module references are borrowed
  67. free(ctx->py);
  68. ctx->py = NULL;
  69. }
  70. if(py_initialized_inside)
  71. Py_Finalize();
  72. }
  73. /*
  74. static int pcilib_py_realloc_string(pcilib_t *ctx, size_t required, size_t *size, char **str) {
  75. char *ptr;
  76. size_t cur = *size;
  77. if ((required + 1) > cur) {
  78. while (cur < required) cur *= 2;
  79. ptr = (char*)realloc(*str, cur);
  80. if (!ptr) return PCILIB_ERROR_MEMORY;
  81. *size = cur;
  82. *str = ptr;
  83. }
  84. ]
  85. return 0;
  86. }
  87. */
  88. static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
  89. int i;
  90. int err = 0;
  91. pcilib_value_t val = {0};
  92. pcilib_register_value_t regval;
  93. char save;
  94. char *reg, *cur;
  95. size_t offset = 0;
  96. size_t size;
  97. char *src;
  98. char *dst;
  99. size_t max_repl = 2 + 2 * sizeof(pcilib_value_t); // the text representation of largest integer
  100. if (value) {
  101. err = pcilib_copy_value(ctx, &val, value);
  102. if (err) return NULL;
  103. err = pcilib_convert_value_type(ctx, &val, PCILIB_TYPE_STRING);
  104. if (err) return NULL;
  105. if (strlen(val.sval) > max_repl)
  106. max_repl = strlen(val.sval);
  107. }
  108. 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
  109. src = strdup(codestr);
  110. dst = (char*)malloc(size); // allocating maximum required space
  111. if ((!src)||(!dst)) {
  112. if (src) free(src);
  113. if (dst) free(dst);
  114. pcilib_error("Failed to allocate memory for string formulas");
  115. return NULL;
  116. }
  117. cur = src;
  118. reg = strchr(src, '$');
  119. while (reg) {
  120. strcpy(dst + offset, cur);
  121. offset += reg - cur;
  122. // find the end of the register name
  123. reg++;
  124. if (*reg == '{') {
  125. reg++;
  126. for (i = 0; (reg[i])&&(reg[i] != '}'); i++);
  127. if (!reg[i]) {
  128. pcilib_error("Python formula (%s) contains unterminated variable reference", codestr);
  129. err = PCILIB_ERROR_INVALID_DATA;
  130. break;
  131. }
  132. } else {
  133. for (i = 0; isalnum(reg[i])||(reg[i] == '_'); i++);
  134. }
  135. save = reg[i];
  136. reg[i] = 0;
  137. // determine replacement value
  138. if (!strcasecmp(reg, "value")) {
  139. if (!value) {
  140. pcilib_error("Python formula (%s) relies on the value of register, but it is not provided", codestr);
  141. err = PCILIB_ERROR_INVALID_REQUEST;
  142. break;
  143. }
  144. strcpy(dst + offset, val.sval);
  145. } else {
  146. if (*reg == '/') {
  147. pcilib_value_t val = {0};
  148. err = pcilib_get_property(ctx, reg, &val);
  149. if (err) break;
  150. err = pcilib_convert_value_type(ctx, &val, PCILIB_TYPE_STRING);
  151. if (err) break;
  152. sprintf(dst + offset, "%s", val.sval);
  153. } else {
  154. err = pcilib_read_register(ctx, NULL, reg, &regval);
  155. if (err) break;
  156. sprintf(dst + offset, "0x%lx", regval);
  157. }
  158. }
  159. offset += strlen(dst + offset);
  160. if (save == '}') i++;
  161. else reg[i] = save;
  162. // Advance to the next register if any
  163. cur = reg + i;
  164. reg = strchr(cur, '$');
  165. }
  166. strcpy(dst + offset, cur);
  167. free(src);
  168. if (err) {
  169. free(dst);
  170. return NULL;
  171. }
  172. return dst;
  173. }
  174. int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
  175. PyGILState_STATE gstate;
  176. char *code;
  177. PyObject* obj;
  178. code = pcilib_py_parse_string(ctx, codestr, value);
  179. if (!code) {
  180. pcilib_error("Failed to parse registers in the code: %s", codestr);
  181. return PCILIB_ERROR_FAILED;
  182. }
  183. gstate = PyGILState_Ensure();
  184. obj = PyRun_String(code, Py_eval_input, ctx->py->global_dict, ctx->py->global_dict);
  185. PyGILState_Release(gstate);
  186. if (!obj) {
  187. pcilib_error("Failed to run the Python code: %s", code);
  188. return PCILIB_ERROR_FAILED;
  189. }
  190. pcilib_debug(VIEWS, "Evaluating a Python string \'%s\' to %lf=\'%s\'", codestr, PyFloat_AsDouble(obj), code);
  191. return pcilib_set_value_from_float(ctx, value, PyFloat_AsDouble(obj));
  192. }
  193. void* pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val)
  194. {
  195. int err;
  196. switch(val->type)
  197. {
  198. case PCILIB_TYPE_INVALID:
  199. pcilib_error("Invalid register output type (PCILIB_TYPE_INVALID)");
  200. return NULL;
  201. case PCILIB_TYPE_STRING:
  202. pcilib_error("Invalid register output type (PCILIB_TYPE_STRING)");
  203. return NULL;
  204. case PCILIB_TYPE_LONG:
  205. {
  206. long ret;
  207. ret = pcilib_get_value_as_int(ctx, val, &err);
  208. if(err)
  209. {
  210. pcilib_error("Failed: pcilib_get_value_as_int (%i)", err);
  211. return NULL;
  212. }
  213. return (PyObject*)PyInt_FromLong((long) ret);
  214. }
  215. case PCILIB_TYPE_DOUBLE:
  216. {
  217. double ret;
  218. ret = pcilib_get_value_as_float(ctx, val, &err);
  219. if(err)
  220. {
  221. pcilib_error("Failed: pcilib_get_value_as_int (%i)", err);
  222. return NULL;
  223. }
  224. return (PyObject*)PyFloat_FromDouble((double) ret);
  225. }
  226. default:
  227. pcilib_error("Invalid register output type (unknown)");
  228. return NULL;
  229. }
  230. }
  231. int pcilib_set_value_from_pyobject(pcilib_t* ctx, void* pyObjVal, pcilib_value_t *val)
  232. {
  233. PyObject* pyVal = pyObjVal;
  234. int err;
  235. if(PyInt_Check(pyVal))
  236. {
  237. err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyVal));
  238. }
  239. else
  240. if(PyFloat_Check(pyVal))
  241. err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(pyVal));
  242. else
  243. if(PyString_Check(pyVal))
  244. err = pcilib_set_value_from_static_string(ctx, val, PyString_AsString(pyVal));
  245. else
  246. {
  247. pcilib_error("Invalid input. Input type should be int, float or string.");
  248. return PCILIB_ERROR_NOTSUPPORTED;
  249. }
  250. if(err)
  251. return err;
  252. return 0;
  253. }
  254. int pcilib_py_init_script(pcilib_t *ctx, char* module_name, pcilib_access_mode_t *mode)
  255. {
  256. //extract module name from script name
  257. char* py_module_name = strtok(module_name, ".");
  258. if(!py_module_name)
  259. {
  260. pcilib_error("Invalid script name specified in XML property (%s)."
  261. " Seems like name doesnt contains extension", module_name);
  262. return PCILIB_ERROR_INVALID_DATA;
  263. }
  264. pcilib_script_s* module = NULL;
  265. HASH_FIND_STR( scripts, module_name, module);
  266. if(module)
  267. {
  268. pcilib_warning("Python module %s is already in hash. Skip init step", module_name);
  269. mode[0] = module->mode;
  270. return 0;
  271. }
  272. //Initialize python module
  273. if(!module_name)
  274. {
  275. pcilib_error("Invalid script name specified in XML property (NULL)");
  276. return PCILIB_ERROR_INVALID_DATA;
  277. }
  278. //import python script
  279. PyObject* py_script_module = PyImport_ImportModule(py_module_name);
  280. if(!py_script_module)
  281. {
  282. printf("Error in import python module: ");
  283. PyErr_Print();
  284. return PCILIB_ERROR_INVALID_DATA;
  285. }
  286. //Initializing pcipywrap module if script use it
  287. PyObject* dict = PyModule_GetDict(py_script_module);
  288. if(PyDict_Contains(dict, PyString_FromString("pcipywrap")))
  289. {
  290. PyObject* pcipywrap_module = PyDict_GetItemString(dict, "pcipywrap");
  291. if(!pcipywrap_module)
  292. {
  293. pcilib_error("Cant extract pcipywrap module from script dictionary");
  294. return PCILIB_ERROR_FAILED;
  295. }
  296. //setting pcilib_t instance
  297. PyObject_CallMethodObjArgs(pcipywrap_module,
  298. PyUnicode_FromString("set_pcilib"),
  299. PyByteArray_FromStringAndSize((const char*)&ctx, sizeof(pcilib_t*)),
  300. NULL);
  301. }
  302. //Success. Create struct and initialize values
  303. module = malloc(sizeof(pcilib_script_s));
  304. module->py_script_module = py_script_module;
  305. module->script_name = malloc(strlen(module_name));
  306. sprintf(module->script_name, "%s", module_name);
  307. module->dict = dict;
  308. //Setting correct mode
  309. mode[0] = 0;
  310. if(PyDict_Contains(dict, PyString_FromString("read_from_register")))
  311. mode[0] |= PCILIB_ACCESS_R;
  312. if(PyDict_Contains(dict, PyString_FromString("write_to_register")))
  313. mode[0] |= PCILIB_ACCESS_W;
  314. module->mode = mode[0];
  315. HASH_ADD_STR( scripts, script_name, module);
  316. return 0;
  317. }
  318. int pcilib_py_free_script(char* module_name)
  319. {
  320. pcilib_script_s *module;
  321. HASH_FIND_STR(scripts, module_name, module);
  322. if(!module)
  323. {
  324. //For some reason it will crash if uncomment. printf same warning is ok
  325. //pcilib_warning("Cant find Python module %s in hash. Seems it has already deleted.", module_name);
  326. return 0;
  327. }
  328. if(module->script_name)
  329. {
  330. free(module->script_name);
  331. module->script_name = NULL;
  332. }
  333. if(module->py_script_module)
  334. {
  335. //PyObject_Free(module->py_script_module);
  336. module->py_script_module = NULL;
  337. }
  338. HASH_DEL(scripts, module);
  339. free(module);
  340. return 0;
  341. }
  342. int pcilib_script_read(pcilib_t *ctx, char* module_name, pcilib_value_t *val)
  343. {
  344. pcilib_script_s *module;
  345. HASH_FIND_STR(scripts, module_name, module);
  346. if(!module)
  347. {
  348. pcilib_error("Failed to find script module (%s) in hash", module_name);
  349. return PCILIB_ERROR_NOTFOUND;
  350. }
  351. int err;
  352. PyObject *ret = PyObject_CallMethod(module->py_script_module, "read_from_register", "()");
  353. if (!ret)
  354. {
  355. printf("Python script error: ");
  356. PyErr_Print();
  357. return PCILIB_ERROR_FAILED;
  358. }
  359. err = pcilib_set_value_from_pyobject(ctx, ret, val);
  360. if(err)
  361. {
  362. pcilib_error("Failed to convert python script return value to internal type: %i", err);
  363. return err;
  364. }
  365. return 0;
  366. }
  367. int pcilib_script_write(pcilib_t *ctx, char* module_name, pcilib_value_t *val)
  368. {
  369. pcilib_script_s *module;
  370. HASH_FIND_STR(scripts, module_name, module);
  371. if(!module)
  372. {
  373. pcilib_error("Failed to find script module (%s) in hash", module_name);
  374. return PCILIB_ERROR_NOTFOUND;
  375. }
  376. PyObject *input = pcilib_get_value_as_pyobject(ctx, val);
  377. if(!input)
  378. {
  379. printf("Failed to convert input value to Python object");
  380. PyErr_Print();
  381. return PCILIB_ERROR_FAILED;
  382. }
  383. PyObject *ret = PyObject_CallMethodObjArgs(module->py_script_module,
  384. PyUnicode_FromString("write_to_register"),
  385. input,
  386. NULL);
  387. if (!ret)
  388. {
  389. printf("Python script error: ");
  390. PyErr_Print();
  391. return PCILIB_ERROR_FAILED;
  392. }
  393. return 0;
  394. }