From ed9d8f285f4d81e1ce8bb5e7a5b9e471a73c1590 Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Tue, 16 Feb 2016 16:30:40 +0100 Subject: 1. Add python thread initialization to pcilib_init_py() -Fix pcilib_script_run_func() work in multithread mode 2. pcilib_close() - Move free_py() code after free views to make view destructors work properly 3. Move script hash to pcilib_py_s 4. Move pcilib_get_logger() pcilib_get_logger_min_prio() and pcilib_get_logger_argument() declarations to error.h 5. Refactor pcilib_get_value_as_pyobject pcilib_set_value_from_pyobject to more unified form 6. Add more memory checks. Fix some string memory allocations. 7. Refactor pcilib_py_s member names. 8. Merge pcilib_script_read() and pcilib_script_write() to pcilib_script_run_func() 9. Update test_pywrap views scripts --- pcilib/error.h | 14 ++++ pcilib/pci.c | 4 +- pcilib/pcilib.h | 15 ---- pcilib/py.c | 180 ++++++++++++++++++++---------------------- pcilib/py.h | 12 +-- pcilib/xml.c | 2 +- pywrap/pcipywrap.c | 11 ++- views/transform.c | 8 +- xml/test_pywrap/test_prop2.py | 10 +-- xml/test_pywrap/test_prop3.py | 9 ++- 10 files changed, 129 insertions(+), 136 deletions(-) diff --git a/pcilib/error.h b/pcilib/error.h index a9f4c0b..95774e9 100644 --- a/pcilib/error.h +++ b/pcilib/error.h @@ -40,6 +40,20 @@ extern "C" { void pcilib_log_message(const char *file, int line, pcilib_log_flags_t flags, pcilib_log_priority_t prio, const char *msg, ...); void pcilib_log_vmessage(const char *file, int line, pcilib_log_flags_t flags, pcilib_log_priority_t prio, const char *msg, va_list va); +/** + * Gets current logger function. + */ +pcilib_logger_t pcilib_get_logger(); + +/** + * Gets current logger min priority. + */ +pcilib_log_priority_t pcilib_get_logger_min_prio(); + +/** + * Gets current logger argument. + */ +void* pcilib_get_logger_argument(); #ifdef __cplusplus } diff --git a/pcilib/pci.c b/pcilib/pci.c index c38097f..58ee4b0 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -306,8 +306,6 @@ void pcilib_close(pcilib_t *ctx) { if (ctx->event_plugin) pcilib_plugin_close(ctx->event_plugin); - - pcilib_free_py(ctx); if (ctx->locks.kmem) pcilib_free_locking(ctx); @@ -349,6 +347,8 @@ void pcilib_close(pcilib_t *ctx) { if (ctx->registers) free(ctx->registers); + + pcilib_free_py(ctx); if (ctx->model) free(ctx->model); diff --git a/pcilib/pcilib.h b/pcilib/pcilib.h index 2458320..c32d1fb 100644 --- a/pcilib/pcilib.h +++ b/pcilib/pcilib.h @@ -263,21 +263,6 @@ extern "C" { */ int pcilib_set_logger(pcilib_log_priority_t min_prio, pcilib_logger_t logger, void *arg); -/** - * Gets current logger function. - */ -pcilib_logger_t pcilib_get_logger(); - -/** - * Gets current logger min priority. - */ -pcilib_log_priority_t pcilib_get_logger_min_prio(); - -/** - * Gets current logger argument. - */ -void* pcilib_get_logger_argument(); - /** public_api_global * @} */ diff --git a/pcilib/py.c b/pcilib/py.c index 20fa546..038dba6 100644 --- a/pcilib/py.c +++ b/pcilib/py.c @@ -11,24 +11,20 @@ #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; + char* name; + PyObject *module; /**< PyModule object, contains script enviroment */ pcilib_access_mode_t mode; UT_hash_handle hh; } pcilib_script_s; -struct pcilib_script_s *scripts = NULL; +struct pcilib_py_s { + PyObject *main_module; + PyObject *global_dict; + int py_initialized_inside; ///< Flag, shows that Py_Initialize has been called inside class + struct pcilib_script_s *scripts; +}; int pcilib_init_py(pcilib_t *ctx) { ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t)); @@ -37,6 +33,12 @@ int pcilib_init_py(pcilib_t *ctx) { if(!Py_IsInitialized()) { Py_Initialize(); + + //Since python is being initializing from c programm, it needs + //to initialize threads to works properly with c threads + PyEval_InitThreads(); + PyEval_ReleaseLock(); + ctx->py->py_initialized_inside = 1; } else @@ -70,6 +72,8 @@ int pcilib_init_py(pcilib_t *ctx) { free(model_path); model_dir_added = 1; } + + ctx->py->scripts = NULL; return 0; } @@ -237,53 +241,60 @@ int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *va return pcilib_set_value_from_float(ctx, value, PyFloat_AsDouble(obj)); } -void* pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val) -{ +pcilib_py_object* pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val, int *ret) +{ int err; switch(val->type) { case PCILIB_TYPE_INVALID: - pcilib_warning("Invalid register output type (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_warning("Invalid register output type (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; - ret = pcilib_get_value_as_int(ctx, val, &err); + long ret_val; + ret_val = pcilib_get_value_as_int(ctx, val, &err); if(err) { - pcilib_error("Failed: pcilib_get_value_as_int (%i)", err); + if (ret) *ret = err; return NULL; } - return (PyObject*)PyInt_FromLong((long) ret); + + if (ret) *ret = 0; + return (PyObject*)PyInt_FromLong((long) ret_val); } case PCILIB_TYPE_DOUBLE: { - double ret; - ret = pcilib_get_value_as_float(ctx, val, &err); + double ret_val; + ret_val = pcilib_get_value_as_float(ctx, val, &err); if(err) { - pcilib_error("Failed: pcilib_get_value_as_int (%i)", err); + if (ret) *ret = err; return NULL; } - return (PyObject*)PyFloat_FromDouble((double) ret); + + if (ret) *ret = 0; + return (PyObject*)PyFloat_FromDouble((double) ret_val); } default: - pcilib_warning("Invalid register output type (unknown)"); + if (ret) *ret = PCILIB_ERROR_NOTSUPPORTED; + pcilib_error("Invalid register output type (unknown)"); return NULL; } } -int pcilib_set_value_from_pyobject(pcilib_t* ctx, void* pyObjVal, pcilib_value_t *val) +int pcilib_set_value_from_pyobject(pcilib_t* ctx, pcilib_value_t *val, pcilib_py_object* pyObjVal) { PyObject* pyVal = pyObjVal; int err; @@ -321,7 +332,7 @@ int pcilib_py_init_script(pcilib_t *ctx, char* module_name, pcilib_access_mode_t } pcilib_script_s* module = NULL; - HASH_FIND_STR( scripts, module_name, module); + 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); @@ -366,10 +377,16 @@ int pcilib_py_init_script(pcilib_t *ctx, char* module_name, pcilib_access_mode_t //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; + if (!module) + return PCILIB_ERROR_MEMORY; + module->module = py_script_module; + module->name = strdup(module_name); + if(!(module->name)) + { + free(module); + return PCILIB_ERROR_MEMORY; + } + sprintf(module->name, "%s", module_name); //Setting correct mode @@ -380,15 +397,15 @@ int pcilib_py_init_script(pcilib_t *ctx, char* module_name, pcilib_access_mode_t mode[0] |= PCILIB_ACCESS_W; module->mode = mode[0]; - HASH_ADD_STR( scripts, script_name, module); + HASH_ADD_STR( ctx->py->scripts, name, module); return 0; } -int pcilib_py_free_script(char* module_name) +int pcilib_py_free_script(pcilib_t *ctx,char* module_name) { pcilib_script_s *module; - HASH_FIND_STR(scripts, module_name, module); + HASH_FIND_STR(ctx->py->scripts, module_name, module); if(!module) { @@ -397,39 +414,51 @@ int pcilib_py_free_script(char* module_name) return 0; } - if(module->script_name) + if(module->name) { - free(module->script_name); - module->script_name = NULL; + free(module->name); + module->name = NULL; } - if(module->py_script_module) + if(module->module) { - //PyObject_Free(module->py_script_module); - module->py_script_module = NULL; + module->module = NULL; } - HASH_DEL(scripts, module); + HASH_DEL(ctx->py->scripts, module); free(module); return 0; } -int pcilib_script_read(pcilib_t *ctx, char* module_name, pcilib_value_t *val) -{ +int pcilib_script_run_func(pcilib_t *ctx, char* module_name, + const char* func_name, pcilib_value_t *val) +{ + int err; pcilib_script_s *module; - HASH_FIND_STR(scripts, module_name, 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; } - int err; - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject *ret = PyObject_CallMethod(module->py_script_module, "read_from_register", "()"); + 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, + input, + NULL); + + + + Py_XDECREF(py_func_name); + Py_XDECREF(input); PyGILState_Release(gstate); + if (!ret) { printf("Python script error: "); @@ -437,55 +466,16 @@ int pcilib_script_read(pcilib_t *ctx, char* module_name, pcilib_value_t *val) return PCILIB_ERROR_FAILED; } - err = pcilib_set_value_from_pyobject(ctx, ret, val); - Py_XDECREF(ret); - - 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) + if(ret != Py_None) { - printf("Failed to convert input value to Python object"); - PyErr_Print(); - return PCILIB_ERROR_FAILED; - } - PyObject *func_name = PyUnicode_FromString("write_to_register"); + err = pcilib_set_value_from_pyobject(ctx, val, ret); + Py_XDECREF(ret); - PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject *ret = PyObject_CallMethodObjArgs(module->py_script_module, - func_name, - input, - NULL); - PyGILState_Release(gstate); - - if (!ret) - { - printf("Python script error: "); - PyErr_Print(); - return PCILIB_ERROR_FAILED; + if(err) + { + pcilib_error("Failed to convert python script return value to internal type: %i", err); + return err; + } } - - //release objects - Py_XDECREF(func_name); - Py_XDECREF(ret); - Py_XDECREF(input); - return 0; } diff --git a/pcilib/py.h b/pcilib/py.h index 09e2b87..9703706 100644 --- a/pcilib/py.h +++ b/pcilib/py.h @@ -4,6 +4,7 @@ #include "pcilib.h" typedef struct pcilib_py_s pcilib_py_t; +typedef void pcilib_py_object; #ifdef __cplusplus extern "C" { @@ -15,10 +16,9 @@ void pcilib_free_py(pcilib_t *ctx); int pcilib_py_init_script(pcilib_t *ctx, char* module_name, pcilib_access_mode_t *mode); -int pcilib_py_free_script(char* module_name); -int pcilib_script_read(pcilib_t *ctx, char* module_name, pcilib_value_t *val); -int pcilib_script_write(pcilib_t *ctx, char* module_name, pcilib_value_t *val); - +int pcilib_py_free_script(pcilib_t *ctx,char* module_name); +int pcilib_script_run_func(pcilib_t *ctx, char* module_name, + const char* func_name, pcilib_value_t *val); /*! * \brief Converts pcilib_value_t to PyObject. @@ -26,7 +26,7 @@ int pcilib_script_write(pcilib_t *ctx, char* module_name, pcilib_value_t *val); * \param val pointer to pcilib_value_t to convert * \return PyObject, containing value. NULL with error message, sended to errstream. */ -void* pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val); +pcilib_py_object* pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val, int *err); /*! @@ -36,7 +36,7 @@ void* pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val); * \param val initialized polymorphic value * \return 0 on success or memory error */ -int pcilib_set_value_from_pyobject(pcilib_t* ctx, void* pyVal, pcilib_value_t *val); +int pcilib_set_value_from_pyobject(pcilib_t* ctx, pcilib_value_t *val, pcilib_py_object* pyObjVal); #ifdef __cplusplus diff --git a/pcilib/xml.c b/pcilib/xml.c index 4e95437..adca34e 100644 --- a/pcilib/xml.c +++ b/pcilib/xml.c @@ -600,7 +600,7 @@ static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xp desc.write_to_reg = value; if ((value)&&(*value)) mode |= PCILIB_ACCESS_W; } else if (!strcasecmp(name, "script")) { - desc.module = malloc(strlen(value)); + desc.module = strdup(value); sprintf(desc.module, "%s", value); break; } diff --git a/pywrap/pcipywrap.c b/pywrap/pcipywrap.c index b1ee630..40dbdfc 100644 --- a/pywrap/pcipywrap.c +++ b/pywrap/pcipywrap.c @@ -127,7 +127,6 @@ PyObject* create_pcilib_instance(const char *fpga_device, const char *model) pcilib_error("#E Failed pcilib_open(%s, %s)", fpga_device, model); return NULL; } - return PyCObject_FromVoidPtr((void*)ctx, close_pcilib_instance); } @@ -204,7 +203,7 @@ PyObject* read_register(const char *regname, const char *bank) return NULL; } - return pcilib_get_value_as_pyobject(__ctx, &val); + return pcilib_get_value_as_pyobject(__ctx, &val, NULL); } /*! @@ -228,7 +227,7 @@ PyObject* write_register(PyObject* val, const char *regname, const char *bank) int err; - err = pcilib_set_value_from_pyobject(__ctx, val, &val_internal); + err = pcilib_set_value_from_pyobject(__ctx, &val_internal, val); if(err) { @@ -279,7 +278,7 @@ PyObject* get_property(const char *prop) return NULL; } - return pcilib_get_value_as_pyobject(__ctx, &val); + return pcilib_get_value_as_pyobject(__ctx, &val, NULL); } /*! @@ -299,7 +298,7 @@ PyObject* set_property(PyObject* val, const char *prop) } pcilib_value_t val_internal = {0}; - err = pcilib_set_value_from_pyobject(__ctx, val, &val_internal); + err = pcilib_set_value_from_pyobject(__ctx, &val_internal, val); if(err) { pcilib_error("#E pcilib_set_value_from_pyobject, (error %i)", err); @@ -339,7 +338,7 @@ void pcilib_pylist_append(PyObject* list, PyObject* value) void add_pcilib_value_to_dict(PyObject* dict, pcilib_value_t* val, const char *name) { - PyObject *py_val = (PyObject*)pcilib_get_value_as_pyobject(__ctx, val); + PyObject *py_val = (PyObject*)pcilib_get_value_as_pyobject(__ctx, val, NULL); if(py_val) pcilib_pydict_set_item(dict, diff --git a/views/transform.c b/views/transform.c index 75b95b2..24434e3 100644 --- a/views/transform.c +++ b/views/transform.c @@ -22,7 +22,8 @@ static int pcilib_transform_view_read(pcilib_t *ctx, pcilib_view_context_t *view if (err) return err; if(v->module) - return pcilib_script_read(ctx, v->module, val); + return err = pcilib_script_run_func(ctx, v->module, + "read_from_register", val); else return pcilib_py_eval_string(ctx, v->read_from_reg, val); } @@ -40,7 +41,8 @@ static int pcilib_transform_view_write(pcilib_t *ctx, pcilib_view_context_t *vie if(v->module) - err = pcilib_script_write(ctx, v->module, &val_copy); + err = pcilib_script_run_func(ctx, v->module, + "write_to_register", &val_copy); else err = pcilib_py_eval_string(ctx, v->write_to_reg, &val_copy); @@ -55,7 +57,7 @@ void pcilib_transform_view_free_description (pcilib_t *ctx, pcilib_view_descript pcilib_transform_view_description_t *v = (pcilib_transform_view_description_t*)(view); if(v->module) - pcilib_py_free_script(v->module); + pcilib_py_free_script(ctx, v->module); } pcilib_view_context_t * pcilib_transform_view_init(pcilib_t *ctx, const pcilib_view_description_t *desc) diff --git a/xml/test_pywrap/test_prop2.py b/xml/test_pywrap/test_prop2.py index 69a2190..d7e10bc 100644 --- a/xml/test_pywrap/test_prop2.py +++ b/xml/test_pywrap/test_prop2.py @@ -1,8 +1,8 @@ import pcipywrap + +def read_from_register(value): + return pcipywrap.get_property('/test/prop3') / 2 -def read_from_register(): - return pcipywrap.get_property('/registers/fpga/reg1') / 2 - -def write_to_register(value): - pcipywrap.set_property(value*3, '/registers/fpga/reg1') +def write_to_register(value): + pcipywrap.set_property(value*2, '/test/prop3') diff --git a/xml/test_pywrap/test_prop3.py b/xml/test_pywrap/test_prop3.py index c1300b3..9d33b63 100644 --- a/xml/test_pywrap/test_prop3.py +++ b/xml/test_pywrap/test_prop3.py @@ -1,4 +1,7 @@ -import os +import pcipywrap + +def read_from_register(value): + return pcipywrap.get_property('/registers/fpga/reg1') -def read_from_register(): - return 10; +def write_to_register(value): + pcipywrap.set_property(value, '/registers/fpga/reg1') -- cgit v1.2.3