From 5d775d64bdec554b9842823bd1c46263210425fd Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Tue, 1 Mar 2016 10:42:40 +0100 Subject: 1. multithreading: - Enable multiprocessing for api_server - Enable mutrithreading for html_server 2. py: - extract pcilib->py bases from pcilib->py functions - add api for interact directly with pcilib->py without pcilib context. 3. pcipywrap - Add scripts handling. --- pcilib/locking.c | 207 ++++++++++++++++++------------------ pcilib/property.c | 4 +- pcilib/py.c | 309 +++++++++++++++++++++++++++++++++++++++--------------- pcilib/py.h | 26 +++++ 4 files changed, 355 insertions(+), 191 deletions(-) (limited to 'pcilib') diff --git a/pcilib/locking.c b/pcilib/locking.c index 71f204e..28aa4c4 100644 --- a/pcilib/locking.c +++ b/pcilib/locking.c @@ -102,118 +102,117 @@ pcilib_lock_t *pcilib_get_lock_by_id(pcilib_t *ctx, pcilib_lock_id_t id) { } pcilib_lock_t *pcilib_get_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, const char *lock_id, ...) { - pcilib_lock_id_t i; - int err, ret; - - pcilib_lock_t *lock; - char buffer[PCILIB_LOCK_SIZE]; - - /* we construct the complete lock_id given the parameters of the function*/ - va_list pa; - va_start(pa, lock_id); - ret = vsnprintf(buffer, PCILIB_LOCK_SIZE, lock_id, pa); - va_end(pa); - - if (ret < 0) { - pcilib_error("Failed to construct the lock id, probably arguments does not match the format string (%s)...", lock_id); - return NULL; - } - - - /* we iterate through locks to see if there is one already with the same name*/ - // Would be nice to have hash here - for (i = 0; i < PCILIB_MAX_LOCKS; i++) { - lock = pcilib_get_lock_by_id(ctx, i); - - const char *name = pcilib_lock_get_name(lock); - if (!name) break; - - if (!strcmp(buffer, name)) { - if ((pcilib_lock_get_flags(lock)&PCILIB_LOCK_FLAG_PERSISTENT) != (flags&PCILIB_LOCK_FLAG_PERSISTENT)) { - if (flags&PCILIB_LOCK_FLAG_PERSISTENT) - pcilib_error("Requesting persistent lock (%s), but requested lock is already existing and is robust", name); - else - pcilib_error("Requesting robust lock (%s), but requested lock is already existing and is persistent", name); - return NULL; - } - -#ifndef HAVE_STDATOMIC_H - if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) { - err = pcilib_lock(ctx->locks.locking); - if (err) { - pcilib_error("Error (%i) obtaining global lock", err); - return NULL; - } - } -#endif /* ! HAVE_STDATOMIC_H */ - /* if yes, we increment its ref variable*/ - pcilib_lock_ref(lock); -#ifndef HAVE_STDATOMIC_H - if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) - pcilib_unlock(ctx->locks.locking); -#endif /* ! HAVE_STDATOMIC_H */ - - return lock; - } - } + pcilib_lock_id_t i; + int err, ret; - if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) { - err = pcilib_lock(ctx->locks.locking); - if (err) { - pcilib_error("Error (%i) obtaining global lock", err); - return NULL; - } - } + pcilib_lock_t *lock; + char buffer[PCILIB_LOCK_SIZE]; - // Make sure it was not allocated meanwhile - for (; i < PCILIB_MAX_LOCKS; i++) { - lock = pcilib_get_lock_by_id(ctx, i); - - const char *name = pcilib_lock_get_name(lock); - if (!name) break; + /* we construct the complete lock_id given the parameters of the function*/ + va_list pa; + va_start(pa, lock_id); + ret = vsnprintf(buffer, PCILIB_LOCK_SIZE, lock_id, pa); + va_end(pa); - if (!strcmp(buffer, name)) { - if ((pcilib_lock_get_flags(lock)&PCILIB_LOCK_FLAG_PERSISTENT) != (flags&PCILIB_LOCK_FLAG_PERSISTENT)) { - if (flags&PCILIB_LOCK_FLAG_PERSISTENT) - pcilib_error("Requesting persistent lock (%s), but requested lock is already existing and is robust", name); - else - pcilib_error("Requesting robust lock (%s), but requested lock is already existing and is persistent", name); - - if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) - pcilib_unlock(ctx->locks.locking); - return NULL; - } + if (ret < 0) { + pcilib_error("Failed to construct the lock id, probably arguments does not match the format string (%s)...", lock_id); + return NULL; + } - pcilib_lock_ref(lock); - if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) - pcilib_unlock(ctx->locks.locking); - return lock; - } - } - if (i == PCILIB_MAX_LOCKS) { - if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) - pcilib_unlock(ctx->locks.locking); - pcilib_error("Failed to create lock (%s), only %u locks is supported", buffer, PCILIB_MAX_LOCKS); - return NULL; - } + /* we iterate through locks to see if there is one already with the same name*/ + // Would be nice to have hash here + for (i = 0; i < PCILIB_MAX_LOCKS; i++) { + lock = pcilib_get_lock_by_id(ctx, i); - /* if the lock did not exist before, then we create it*/ - err = pcilib_init_lock(lock, flags, buffer); - - if (err) { - pcilib_error("Lock initialization failed with error %i", err); + const char *name = pcilib_lock_get_name(lock); + if (!name) break; - if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) - pcilib_unlock(ctx->locks.locking); - - return NULL; - } - - if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) - pcilib_unlock(ctx->locks.locking); + if (!strcmp(buffer, name)) { + if ((pcilib_lock_get_flags(lock)&PCILIB_LOCK_FLAG_PERSISTENT) != (flags&PCILIB_LOCK_FLAG_PERSISTENT)) { + if (flags&PCILIB_LOCK_FLAG_PERSISTENT) + pcilib_error("Requesting persistent lock (%s), but requested lock is already existing and is robust", name); + else + pcilib_error("Requesting robust lock (%s), but requested lock is already existing and is persistent", name); + return NULL; + } - return lock; +#ifndef HAVE_STDATOMIC_H + if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) { + err = pcilib_lock(ctx->locks.locking); + if (err) { + pcilib_error("Error (%i) obtaining global lock", err); + return NULL; + } + } +#endif /* ! HAVE_STDATOMIC_H */ + /* if yes, we increment its ref variable*/ + pcilib_lock_ref(lock); + #ifndef HAVE_STDATOMIC_H + if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) + pcilib_unlock(ctx->locks.locking); + #endif /* ! HAVE_STDATOMIC_H */ + return lock; + } + } + + if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) { + err = pcilib_lock(ctx->locks.locking); + if (err) { + pcilib_error("Error (%i) obtaining global lock", err); + return NULL; + } + } + + // Make sure it was not allocated meanwhile + for (; i < PCILIB_MAX_LOCKS; i++) { + lock = pcilib_get_lock_by_id(ctx, i); + + const char *name = pcilib_lock_get_name(lock); + if (!name) break; + + if (!strcmp(buffer, name)) { + if ((pcilib_lock_get_flags(lock)&PCILIB_LOCK_FLAG_PERSISTENT) != (flags&PCILIB_LOCK_FLAG_PERSISTENT)) { + if (flags&PCILIB_LOCK_FLAG_PERSISTENT) + pcilib_error("Requesting persistent lock (%s), but requested lock is already existing and is robust", name); + else + pcilib_error("Requesting robust lock (%s), but requested lock is already existing and is persistent", name); + + if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) + pcilib_unlock(ctx->locks.locking); + return NULL; + } + + pcilib_lock_ref(lock); + if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) + pcilib_unlock(ctx->locks.locking); + return lock; + } + } + + if (i == PCILIB_MAX_LOCKS) { + if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) + pcilib_unlock(ctx->locks.locking); + pcilib_error("Failed to create lock (%s), only %u locks is supported", buffer, PCILIB_MAX_LOCKS); + return NULL; + } + + /* if the lock did not exist before, then we create it*/ + err = pcilib_init_lock(lock, flags, buffer); + + if (err) { + pcilib_error("Lock initialization failed with error %i", err); + + if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) + pcilib_unlock(ctx->locks.locking); + + return NULL; + } + + if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) + pcilib_unlock(ctx->locks.locking); + + return lock; } void pcilib_return_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, pcilib_lock_t *lock) { diff --git a/pcilib/property.c b/pcilib/property.c index dfab9a6..1dba1be 100644 --- a/pcilib/property.c +++ b/pcilib/property.c @@ -226,8 +226,8 @@ pcilib_property_info_t *pcilib_get_property_list(pcilib_t *ctx, const char *bran } HASH_ITER(hh, dir_hash, dir, dir_tmp) { - HASH_DEL(dir_hash, dir); - free(dir); + HASH_DEL(dir_hash, dir); + free(dir); } HASH_CLEAR(hh, dir_hash); diff --git a/pcilib/py.c b/pcilib/py.c index 6cf9fdc..934c11f 100644 --- a/pcilib/py.c +++ b/pcilib/py.c @@ -89,8 +89,6 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag #endif /* HAVE_PYTHON */ } - - int pcilib_init_py(pcilib_t *ctx) { #ifdef HAVE_PYTHON ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t)); @@ -143,8 +141,6 @@ int pcilib_init_py(pcilib_t *ctx) { int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) { #ifdef HAVE_PYTHON int err = 0; - PyObject *pypath, *pynewdir; - PyObject *pydict, *pystr, *pyret = NULL; char *script_dir; const char *model_dir = getenv("PCILIB_MODEL_DIR"); @@ -160,83 +156,59 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) { 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; - } + err = pcilib_py_ctx_add_script_dir(ctx->py, script_dir); + if(err) return err; +#endif /* HAVE_PYTHON */ - pynewdir = PyString_FromString(script_dir); - if (!pynewdir) { - pcilib_python_error("Can't create python string"); - return PCILIB_ERROR_MEMORY; + return 0; +} + +void pcilib_py_free_hash(pcilib_py_t *ctx_py) { + 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; } - - // Checking if the directory already in the path - pydict = PyDict_New(); - if (pydict) { - pystr = PyString_FromString("cur"); - if (pystr) { - PyDict_SetItem(pydict, pystr, pynewdir); - Py_DECREF(pystr); - } +} - pystr = PyString_FromString("path"); - if (pystr) { - PyDict_SetItem(pydict, pystr, pypath); - Py_DECREF(pystr); - } +void pcilib_free_py_ctx(pcilib_py_t *ctx_py) { +#ifdef HAVE_PYTHON + int finalyze = 0; - pyret = PyRun_String("cur in path", Py_eval_input, ctx->py->global_dict, pydict); - Py_DECREF(pydict); - } + if (ctx_py) { + if (ctx_py->finalyze) finalyze = 1; - if ((pyret == Py_False)&&(PyList_Append(pypath, pynewdir) == -1)) - err = PCILIB_ERROR_FAILED; + pcilib_py_free_hash(ctx_py); - if (pyret) Py_DECREF(pyret); - Py_DECREF(pynewdir); + if (ctx_py->pcilib_pywrap) + Py_DECREF(ctx_py->pcilib_pywrap); - if (err) { - pcilib_python_error("Can't add directory (%s) to python path", script_dir); - return err; - } -#endif /* HAVE_PYTHON */ + free(ctx_py); + } - return 0; + if (finalyze) + Py_Finalize(); +#endif /* HAVE_PYTHON */ } + void pcilib_free_py(pcilib_t *ctx) { #ifdef HAVE_PYTHON - int finalyze = 0; - - 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; - } - - if (ctx->py->pcilib_pywrap) - Py_DECREF(ctx->py->pcilib_pywrap); - - free(ctx->py); - ctx->py = NULL; - } - - if (finalyze) - Py_Finalize(); + pcilib_free_py_ctx(ctx->py); + ctx->py = NULL; #endif /* HAVE_PYTHON */ } int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) { + return pcilib_py_ctx_load_script(ctx->py, script_name); +} + +int pcilib_py_ctx_load_script(pcilib_py_t *ctx_py, const char *script_name) { #ifdef HAVE_PYTHON PyObject* pymodule; pcilib_script_t *module = NULL; @@ -252,7 +224,7 @@ int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) { } *py = 0; - HASH_FIND_STR(ctx->py->script_hash, script_name, module); + HASH_FIND_STR(ctx_py->script_hash, script_name, module); if (module) return 0; pymodule = PyImport_ImportModule(module_name); @@ -266,7 +238,7 @@ int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) { module->module = pymodule; module->name = script_name; - HASH_ADD_KEYPTR(hh, ctx->py->script_hash, module->name, strlen(module->name), module); + HASH_ADD_STR(ctx_py->script_hash, name, module); #endif /* HAVE_PYTHON */ return 0; } @@ -527,51 +499,218 @@ int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *va 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 *pyval = NULL; + + if (val) { + pyval = pcilib_get_value_as_pyobject(ctx, val, &err); + if (err) return err; + } + + PyObject* pyret = pcilib_py_ctx_eval_func(ctx->py, script_name, + func_name, pyval, &err); + if (err) return err; + + if ((val)&&(pyret != Py_None)) + err = pcilib_set_value_from_pyobject(ctx, val, pyret); + + Py_DECREF(pyret); + + return err; +#else /* HAVE_PYTHON */ + pcilib_error("Python is not supported"); + return PCILIB_ERROR_NOTSUPPORTED; +#endif /* HAVE_PYTHON */ +} + +pcilib_py_object* pcilib_py_ctx_eval_func(pcilib_py_t *ctx_py, + const char *script_name, + const char *func_name, + pcilib_py_object *pyval, + int *err) { +#ifdef HAVE_PYTHON PyObject *pyfunc; - PyObject *pyval = NULL, *pyret; + PyObject *pyret; pcilib_script_t *module = NULL; - HASH_FIND_STR(ctx->py->script_hash, script_name, module); + 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; - } - - if (val) { - pyval = pcilib_get_value_as_pyobject(ctx, val, &err); - if (err) return err; + if(err) *err = PCILIB_ERROR_NOTFOUND; + return NULL; } - + PyGILState_STATE gstate = PyGILState_Ensure(); pyfunc = PyUnicode_FromString(func_name); if (!pyfunc) { if (pyval) Py_DECREF(pyval); PyGILState_Release(gstate); - return PCILIB_ERROR_MEMORY; + if(err) *err = PCILIB_ERROR_MEMORY; + return NULL; } - pyret = PyObject_CallMethodObjArgs(module->module, pyfunc, ctx->py->pcilib_pywrap, pyval, NULL); + pyret = PyObject_CallMethodObjArgs(module->module, + pyfunc, + ctx_py->pcilib_pywrap, + pyval, + NULL); Py_DECREF(pyfunc); Py_DECREF(pyval); - + if (!pyret) { PyGILState_Release(gstate); - pcilib_python_error("Error executing function (%s) of python script (%s)", func_name, script_name); + pcilib_python_error("Error executing function (%s) of python " + "script (%s)", func_name, script_name); + if(err) *err = PCILIB_ERROR_FAILED; + return NULL; + } + PyGILState_Release(gstate); + + return pyret; + +#else /* HAVE_PYTHON */ + pcilib_error("Python is not supported"); + if(err) *err = PCILIB_ERROR_NOTSUPPORTED; + return NULL; +#endif /* HAVE_PYTHON */ +} + +int pcilib_py_ctx_add_script_dir(pcilib_py_t *ctx_py, const char *dir) { +#ifdef HAVE_PYTHON + int err = 0; + PyObject *pypath, *pynewdir; + PyObject *pydict, *pystr, *pyret = NULL; + + //const char *model_dir = getenv("PCILIB_MODEL_DIR"); + //if (!model_dir) model_dir = PCILIB_MODEL_DIR; + + pypath = PySys_GetObject("path"); + if (!pypath) { + pcilib_python_error("Can't get python path"); return PCILIB_ERROR_FAILED; } - if ((val)&&(pyret != Py_None)) - err = pcilib_set_value_from_pyobject(ctx, val, pyret); + pynewdir = PyString_FromString(dir); + if (!pynewdir) { + pcilib_python_error("Can't create python string"); + return PCILIB_ERROR_MEMORY; + } - Py_DECREF(pyret); - PyGILState_Release(gstate); + // Checking if the directory already in the path + pydict = PyDict_New(); + if (pydict) { + pystr = PyString_FromString("cur"); + if (pystr) { + PyDict_SetItem(pydict, pystr, pynewdir); + Py_DECREF(pystr); + } else { + pcilib_python_error("Can't create python string"); + return PCILIB_ERROR_MEMORY; + } - return err; + pystr = PyString_FromString("path"); + if (pystr) { + PyDict_SetItem(pydict, pystr, pypath); + Py_DECREF(pystr); + } else { + pcilib_python_error("Can't create python string"); + return PCILIB_ERROR_MEMORY; + } + + pyret = PyRun_String("cur in path", Py_eval_input, ctx_py->global_dict, pydict); + Py_DECREF(pydict); + + } else { + pcilib_python_error("Can't create python dict"); + return PCILIB_ERROR_MEMORY; + } + + if ((pyret == Py_False)&&(PyList_Append(pypath, pynewdir) == -1)) + err = PCILIB_ERROR_FAILED; + + if (pyret) Py_DECREF(pyret); + Py_DECREF(pynewdir); + + if (err) { + pcilib_python_error("Can't add directory (%s) to python path", dir); + return err; + } + return 0; #else /* HAVE_PYTHON */ pcilib_error("Python is not supported"); return PCILIB_ERROR_NOTSUPPORTED; #endif /* HAVE_PYTHON */ } + +pcilib_py_t* pcilib_init_py_ctx(pcilib_py_t* in, int *err) { + pcilib_py_t* out = (pcilib_py_t*)malloc(sizeof(pcilib_py_t)); + if (!out) { + if(err) *err = PCILIB_ERROR_MEMORY; + return NULL; + } + + out->finalyze = 0; + out->main_module = in->main_module; + out->global_dict = in->global_dict; + out->pcilib_pywrap = in->pcilib_pywrap; + out->script_hash = NULL; + + if(err) *err = 0; + return out; +} + +/*! + * \brief Wrap for PyDict_SetItem, with decrease reference counting after set. + */ +void pcilib_pydict_set_item(pcilib_py_object* dict, pcilib_py_object* name, pcilib_py_object* value) +{ + PyDict_SetItem(dict, + name, + value); + Py_XDECREF(name); + Py_XDECREF(value); +} + +/*! + * \brief Wrap for PyList_Append, with decrease reference counting after append. + */ +void pcilib_pylist_append(pcilib_py_object* list, pcilib_py_object* value) +{ + PyList_Append(list, value); + Py_XDECREF(value); +} + +pcilib_py_object *pcilib_py_ctx_get_scripts_info(pcilib_py_t *ctx_py) { + + PyObject* pyList = PyList_New(0); + + if (ctx_py->script_hash) { + pcilib_script_t *script, *script_tmp; + + HASH_ITER(hh, ctx_py->script_hash, script, script_tmp) { + + PyObject* pylistItem = PyDict_New(); + pcilib_pydict_set_item(pylistItem, + PyString_FromString("name"), + PyString_FromString(script->name)); + + PyObject* dict = PyModule_GetDict(script->module); + if (dict) { + PyObject* pystr = PyString_FromString("description"); + if (pystr) { + if (PyDict_Contains(dict, pystr)) { + PyDict_SetItem(pylistItem, + pystr, + PyDict_GetItem(dict, pystr)); + } + Py_DECREF(pystr); + } + } + pcilib_pylist_append(pyList, pylistItem); + + } + } + return pyList; +} diff --git a/pcilib/py.h b/pcilib/py.h index c372a09..549eddf 100644 --- a/pcilib/py.h +++ b/pcilib/py.h @@ -118,6 +118,32 @@ int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *va */ int pcilib_py_eval_func(pcilib_t *ctx, const char *script, const char *func, pcilib_value_t *val); + +/** Clone pcilib_py_t content without scripts hash + * @param[in] in - pcilib_py_t content to clone + * @param[out] err - error + * @return - NULL or cloned pcilib_py_t content pointer on success + */ +pcilib_py_t* pcilib_init_py_ctx(pcilib_py_t* in, int *err); +pcilib_py_object* pcilib_py_ctx_eval_func(pcilib_py_t *ctx_py, + const char *script_name, + const char *func_name, + pcilib_py_object *pyval, + int *err); +int pcilib_py_ctx_add_script_dir(pcilib_py_t *ctx_py, const char *dir); +void pcilib_free_py_ctx(pcilib_py_t *ctx_py); +int pcilib_py_ctx_load_script(pcilib_py_t *ctx_py, const char *script_name); +pcilib_py_object *pcilib_py_ctx_get_scripts_info(pcilib_py_t *ctx_py); + +/*! + * \brief Wrap for PyDict_SetItem, with decrease reference counting after set. + */ +void pcilib_pydict_set_item(pcilib_py_object* dict, pcilib_py_object* name, pcilib_py_object* value); + +/*! + * \brief Wrap for PyList_Append, with decrease reference counting after append. + */ +void pcilib_pylist_append(pcilib_py_object* list, pcilib_py_object* value); #ifdef __cplusplus } #endif -- cgit v1.2.3 From 269b0985bd5830e27f6dedb04a05d76f52acb68c Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Tue, 1 Mar 2016 17:17:46 +0100 Subject: update documentation --- pcilib/py.h | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'pcilib') diff --git a/pcilib/py.h b/pcilib/py.h index 549eddf..62ce7db 100644 --- a/pcilib/py.h +++ b/pcilib/py.h @@ -125,23 +125,55 @@ int pcilib_py_eval_func(pcilib_t *ctx, const char *script, const char *func, pci * @return - NULL or cloned pcilib_py_t content pointer on success */ pcilib_py_t* pcilib_init_py_ctx(pcilib_py_t* in, int *err); + +/** + * @brief pcilib_t independent variant pcilib_free_py + * @param ctx_py[in,out] - pcilib_py_t context + */ +void pcilib_free_py_ctx(pcilib_py_t *ctx_py); + +/** pcilib_t independent variant of pcilib_py_eval_func() + * @param ctx_py[in,out] - pcilib_py_t context + * @param name[in] - script name + * @param name[in] - function name + * @param pyval[in] - input value (will be decref in this fucntion) + * @param err[out] - error + * @return value returned by python function + */ pcilib_py_object* pcilib_py_ctx_eval_func(pcilib_py_t *ctx_py, - const char *script_name, + const char *name, const char *func_name, pcilib_py_object *pyval, int *err); -int pcilib_py_ctx_add_script_dir(pcilib_py_t *ctx_py, const char *dir); -void pcilib_free_py_ctx(pcilib_py_t *ctx_py); -int pcilib_py_ctx_load_script(pcilib_py_t *ctx_py, const char *script_name); + +/** + * @brief pcilib_t independent variant of pcilib_py_add_script_dir + * @param ctx_py[in,out] - pcilib_py_t context + * @param[in] location - NULL or path to additional scripts + * @return + */ +int pcilib_py_ctx_add_script_dir(pcilib_py_t *ctx_py, const char *location); + +/** + * @brief pcilib_t independent variant of pcilib_py_load_script + * @param ctx_py[in,out] - pcilib_py_t context + * @param[in] name - script name, the passed variable is referenced and, hence, should have static duration + * @return + */ +int pcilib_py_ctx_load_script(pcilib_py_t *ctx_py, const char *name); + +/** + * @brief Returns information about scripts aviable in model + * @param ctx_py[in,out] - pcilib_py_t context + * @return List with information about scripts + */ pcilib_py_object *pcilib_py_ctx_get_scripts_info(pcilib_py_t *ctx_py); -/*! - * \brief Wrap for PyDict_SetItem, with decrease reference counting after set. +/** Wrap for PyDict_SetItem, with decrease reference counting after set. */ void pcilib_pydict_set_item(pcilib_py_object* dict, pcilib_py_object* name, pcilib_py_object* value); -/*! - * \brief Wrap for PyList_Append, with decrease reference counting after append. +/** Wrap for PyList_Append, with decrease reference counting after append. */ void pcilib_pylist_append(pcilib_py_object* list, pcilib_py_object* value); #ifdef __cplusplus -- cgit v1.2.3 From 8719b84a95805d109e21c20f05a0164315e1b38a Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Wed, 2 Mar 2016 10:26:13 +0100 Subject: Move scripts handing code from py.c to Python wrap --- pcilib/py.c | 313 +++++++++++++++++------------------------------------------- pcilib/py.h | 58 ----------- 2 files changed, 87 insertions(+), 284 deletions(-) (limited to 'pcilib') diff --git a/pcilib/py.c b/pcilib/py.c index 934c11f..699cd59 100644 --- a/pcilib/py.c +++ b/pcilib/py.c @@ -89,6 +89,8 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag #endif /* HAVE_PYTHON */ } + + int pcilib_init_py(pcilib_t *ctx) { #ifdef HAVE_PYTHON ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t)); @@ -117,13 +119,13 @@ int pcilib_init_py(pcilib_t *ctx) { return PCILIB_ERROR_FAILED; } - PyObject *pywrap = PyImport_ImportModule("pcipywrap"); + PyObject *pywrap = PyImport_ImportModule("pcilib"); if (!pywrap) { pcilib_python_error("Error importing pcilib python wrapper"); return PCILIB_ERROR_FAILED; } - PyObject *mod_name = PyString_FromString("Pcipywrap"); + PyObject *mod_name = PyString_FromString("Pcilib"); PyObject *pyctx = PyCObject_FromVoidPtr(ctx, NULL); ctx->py->pcilib_pywrap = PyObject_CallMethodObjArgs(pywrap, mod_name, pyctx, NULL); Py_XDECREF(pyctx); @@ -141,6 +143,8 @@ int pcilib_init_py(pcilib_t *ctx) { int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) { #ifdef HAVE_PYTHON int err = 0; + PyObject *pypath, *pynewdir; + PyObject *pydict, *pystr, *pyret = NULL; char *script_dir; const char *model_dir = getenv("PCILIB_MODEL_DIR"); @@ -156,59 +160,83 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) { sprintf(script_dir, "%s/%s", model_dir, dir); } - err = pcilib_py_ctx_add_script_dir(ctx->py, script_dir); - if(err) return err; -#endif /* HAVE_PYTHON */ - - return 0; -} - -void pcilib_py_free_hash(pcilib_py_t *ctx_py) { - 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; + pypath = PySys_GetObject("path"); + if (!pypath) { + pcilib_python_error("Can't get python path"); + return PCILIB_ERROR_FAILED; } -} -void pcilib_free_py_ctx(pcilib_py_t *ctx_py) { -#ifdef HAVE_PYTHON - int finalyze = 0; + pynewdir = PyString_FromString(script_dir); + if (!pynewdir) { + pcilib_python_error("Can't create python string"); + return PCILIB_ERROR_MEMORY; + } + + // Checking if the directory already in the path + pydict = PyDict_New(); + if (pydict) { + pystr = PyString_FromString("cur"); + if (pystr) { + PyDict_SetItem(pydict, pystr, pynewdir); + Py_DECREF(pystr); + } - if (ctx_py) { - if (ctx_py->finalyze) finalyze = 1; + pystr = PyString_FromString("path"); + if (pystr) { + PyDict_SetItem(pydict, pystr, pypath); + Py_DECREF(pystr); + } - pcilib_py_free_hash(ctx_py); + pyret = PyRun_String("cur in path", Py_eval_input, ctx->py->global_dict, pydict); + Py_DECREF(pydict); + } - if (ctx_py->pcilib_pywrap) - Py_DECREF(ctx_py->pcilib_pywrap); + if ((pyret == Py_False)&&(PyList_Append(pypath, pynewdir) == -1)) + err = PCILIB_ERROR_FAILED; - free(ctx_py); - } + if (pyret) Py_DECREF(pyret); + Py_DECREF(pynewdir); - if (finalyze) - Py_Finalize(); + if (err) { + pcilib_python_error("Can't add directory (%s) to python path", script_dir); + return err; + } #endif /* HAVE_PYTHON */ -} + return 0; +} void pcilib_free_py(pcilib_t *ctx) { #ifdef HAVE_PYTHON - pcilib_free_py_ctx(ctx->py); - ctx->py = NULL; + int finalyze = 0; + + 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; + } + + if (ctx->py->pcilib_pywrap) + Py_DECREF(ctx->py->pcilib_pywrap); + + free(ctx->py); + ctx->py = NULL; + } + + if (finalyze) + Py_Finalize(); #endif /* HAVE_PYTHON */ } int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) { - return pcilib_py_ctx_load_script(ctx->py, script_name); -} - -int pcilib_py_ctx_load_script(pcilib_py_t *ctx_py, const char *script_name) { #ifdef HAVE_PYTHON PyObject* pymodule; pcilib_script_t *module = NULL; @@ -224,7 +252,7 @@ int pcilib_py_ctx_load_script(pcilib_py_t *ctx_py, const char *script_name) { } *py = 0; - HASH_FIND_STR(ctx_py->script_hash, script_name, module); + HASH_FIND_STR(ctx->py->script_hash, script_name, module); if (module) return 0; pymodule = PyImport_ImportModule(module_name); @@ -238,7 +266,7 @@ int pcilib_py_ctx_load_script(pcilib_py_t *ctx_py, const char *script_name) { module->module = pymodule; module->name = script_name; - HASH_ADD_STR(ctx_py->script_hash, name, module); + HASH_ADD_KEYPTR(hh, ctx->py->script_hash, module->name, strlen(module->name), module); #endif /* HAVE_PYTHON */ return 0; } @@ -499,218 +527,51 @@ int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *va 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 *pyval = NULL; - - if (val) { - pyval = pcilib_get_value_as_pyobject(ctx, val, &err); - if (err) return err; - } - - PyObject* pyret = pcilib_py_ctx_eval_func(ctx->py, script_name, - func_name, pyval, &err); - if (err) return err; - - if ((val)&&(pyret != Py_None)) - err = pcilib_set_value_from_pyobject(ctx, val, pyret); - - Py_DECREF(pyret); - - return err; -#else /* HAVE_PYTHON */ - pcilib_error("Python is not supported"); - return PCILIB_ERROR_NOTSUPPORTED; -#endif /* HAVE_PYTHON */ -} - -pcilib_py_object* pcilib_py_ctx_eval_func(pcilib_py_t *ctx_py, - const char *script_name, - const char *func_name, - pcilib_py_object *pyval, - int *err) { -#ifdef HAVE_PYTHON PyObject *pyfunc; - PyObject *pyret; + PyObject *pyval = NULL, *pyret; pcilib_script_t *module = NULL; - HASH_FIND_STR(ctx_py->script_hash, script_name, module); + HASH_FIND_STR(ctx->py->script_hash, script_name, module); if (!module) { pcilib_error("Script (%s) is not loaded", script_name); - if(err) *err = PCILIB_ERROR_NOTFOUND; - return NULL; + return PCILIB_ERROR_NOTFOUND; } - + + if (val) { + pyval = pcilib_get_value_as_pyobject(ctx, val, &err); + if (err) return err; + } + PyGILState_STATE gstate = PyGILState_Ensure(); pyfunc = PyUnicode_FromString(func_name); if (!pyfunc) { if (pyval) Py_DECREF(pyval); PyGILState_Release(gstate); - if(err) *err = PCILIB_ERROR_MEMORY; - return NULL; + return PCILIB_ERROR_MEMORY; } - pyret = PyObject_CallMethodObjArgs(module->module, - pyfunc, - ctx_py->pcilib_pywrap, - pyval, - NULL); + pyret = PyObject_CallMethodObjArgs(module->module, pyfunc, ctx->py->pcilib_pywrap, pyval, NULL); Py_DECREF(pyfunc); Py_DECREF(pyval); - + if (!pyret) { PyGILState_Release(gstate); - pcilib_python_error("Error executing function (%s) of python " - "script (%s)", func_name, script_name); - if(err) *err = PCILIB_ERROR_FAILED; - return NULL; - } - PyGILState_Release(gstate); - - return pyret; - -#else /* HAVE_PYTHON */ - pcilib_error("Python is not supported"); - if(err) *err = PCILIB_ERROR_NOTSUPPORTED; - return NULL; -#endif /* HAVE_PYTHON */ -} - -int pcilib_py_ctx_add_script_dir(pcilib_py_t *ctx_py, const char *dir) { -#ifdef HAVE_PYTHON - int err = 0; - PyObject *pypath, *pynewdir; - PyObject *pydict, *pystr, *pyret = NULL; - - //const char *model_dir = getenv("PCILIB_MODEL_DIR"); - //if (!model_dir) model_dir = PCILIB_MODEL_DIR; - - pypath = PySys_GetObject("path"); - if (!pypath) { - pcilib_python_error("Can't get python path"); + pcilib_python_error("Error executing function (%s) of python script (%s)", func_name, script_name); return PCILIB_ERROR_FAILED; } - pynewdir = PyString_FromString(dir); - if (!pynewdir) { - pcilib_python_error("Can't create python string"); - return PCILIB_ERROR_MEMORY; - } - - // Checking if the directory already in the path - pydict = PyDict_New(); - if (pydict) { - pystr = PyString_FromString("cur"); - if (pystr) { - PyDict_SetItem(pydict, pystr, pynewdir); - Py_DECREF(pystr); - } else { - pcilib_python_error("Can't create python string"); - return PCILIB_ERROR_MEMORY; - } - - pystr = PyString_FromString("path"); - if (pystr) { - PyDict_SetItem(pydict, pystr, pypath); - Py_DECREF(pystr); - } else { - pcilib_python_error("Can't create python string"); - return PCILIB_ERROR_MEMORY; - } - - pyret = PyRun_String("cur in path", Py_eval_input, ctx_py->global_dict, pydict); - Py_DECREF(pydict); - - } else { - pcilib_python_error("Can't create python dict"); - return PCILIB_ERROR_MEMORY; - } - - if ((pyret == Py_False)&&(PyList_Append(pypath, pynewdir) == -1)) - err = PCILIB_ERROR_FAILED; + if ((val)&&(pyret != Py_None)) + err = pcilib_set_value_from_pyobject(ctx, val, pyret); - if (pyret) Py_DECREF(pyret); - Py_DECREF(pynewdir); + Py_DECREF(pyret); + PyGILState_Release(gstate); - if (err) { - pcilib_python_error("Can't add directory (%s) to python path", dir); - return err; - } - return 0; + return err; #else /* HAVE_PYTHON */ pcilib_error("Python is not supported"); return PCILIB_ERROR_NOTSUPPORTED; #endif /* HAVE_PYTHON */ } - -pcilib_py_t* pcilib_init_py_ctx(pcilib_py_t* in, int *err) { - pcilib_py_t* out = (pcilib_py_t*)malloc(sizeof(pcilib_py_t)); - if (!out) { - if(err) *err = PCILIB_ERROR_MEMORY; - return NULL; - } - - out->finalyze = 0; - out->main_module = in->main_module; - out->global_dict = in->global_dict; - out->pcilib_pywrap = in->pcilib_pywrap; - out->script_hash = NULL; - - if(err) *err = 0; - return out; -} - -/*! - * \brief Wrap for PyDict_SetItem, with decrease reference counting after set. - */ -void pcilib_pydict_set_item(pcilib_py_object* dict, pcilib_py_object* name, pcilib_py_object* value) -{ - PyDict_SetItem(dict, - name, - value); - Py_XDECREF(name); - Py_XDECREF(value); -} - -/*! - * \brief Wrap for PyList_Append, with decrease reference counting after append. - */ -void pcilib_pylist_append(pcilib_py_object* list, pcilib_py_object* value) -{ - PyList_Append(list, value); - Py_XDECREF(value); -} - -pcilib_py_object *pcilib_py_ctx_get_scripts_info(pcilib_py_t *ctx_py) { - - PyObject* pyList = PyList_New(0); - - if (ctx_py->script_hash) { - pcilib_script_t *script, *script_tmp; - - HASH_ITER(hh, ctx_py->script_hash, script, script_tmp) { - - PyObject* pylistItem = PyDict_New(); - pcilib_pydict_set_item(pylistItem, - PyString_FromString("name"), - PyString_FromString(script->name)); - - PyObject* dict = PyModule_GetDict(script->module); - if (dict) { - PyObject* pystr = PyString_FromString("description"); - if (pystr) { - if (PyDict_Contains(dict, pystr)) { - PyDict_SetItem(pylistItem, - pystr, - PyDict_GetItem(dict, pystr)); - } - Py_DECREF(pystr); - } - } - pcilib_pylist_append(pyList, pylistItem); - - } - } - return pyList; -} diff --git a/pcilib/py.h b/pcilib/py.h index 62ce7db..c372a09 100644 --- a/pcilib/py.h +++ b/pcilib/py.h @@ -118,64 +118,6 @@ int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *va */ int pcilib_py_eval_func(pcilib_t *ctx, const char *script, const char *func, pcilib_value_t *val); - -/** Clone pcilib_py_t content without scripts hash - * @param[in] in - pcilib_py_t content to clone - * @param[out] err - error - * @return - NULL or cloned pcilib_py_t content pointer on success - */ -pcilib_py_t* pcilib_init_py_ctx(pcilib_py_t* in, int *err); - -/** - * @brief pcilib_t independent variant pcilib_free_py - * @param ctx_py[in,out] - pcilib_py_t context - */ -void pcilib_free_py_ctx(pcilib_py_t *ctx_py); - -/** pcilib_t independent variant of pcilib_py_eval_func() - * @param ctx_py[in,out] - pcilib_py_t context - * @param name[in] - script name - * @param name[in] - function name - * @param pyval[in] - input value (will be decref in this fucntion) - * @param err[out] - error - * @return value returned by python function - */ -pcilib_py_object* pcilib_py_ctx_eval_func(pcilib_py_t *ctx_py, - const char *name, - const char *func_name, - pcilib_py_object *pyval, - int *err); - -/** - * @brief pcilib_t independent variant of pcilib_py_add_script_dir - * @param ctx_py[in,out] - pcilib_py_t context - * @param[in] location - NULL or path to additional scripts - * @return - */ -int pcilib_py_ctx_add_script_dir(pcilib_py_t *ctx_py, const char *location); - -/** - * @brief pcilib_t independent variant of pcilib_py_load_script - * @param ctx_py[in,out] - pcilib_py_t context - * @param[in] name - script name, the passed variable is referenced and, hence, should have static duration - * @return - */ -int pcilib_py_ctx_load_script(pcilib_py_t *ctx_py, const char *name); - -/** - * @brief Returns information about scripts aviable in model - * @param ctx_py[in,out] - pcilib_py_t context - * @return List with information about scripts - */ -pcilib_py_object *pcilib_py_ctx_get_scripts_info(pcilib_py_t *ctx_py); - -/** Wrap for PyDict_SetItem, with decrease reference counting after set. - */ -void pcilib_pydict_set_item(pcilib_py_object* dict, pcilib_py_object* name, pcilib_py_object* value); - -/** Wrap for PyList_Append, with decrease reference counting after append. - */ -void pcilib_pylist_append(pcilib_py_object* list, pcilib_py_object* value); #ifdef __cplusplus } #endif -- cgit v1.2.3 From 02d0026e2df2ba5c68c0c1a67aec4437c9e8e8f3 Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Wed, 2 Mar 2016 14:38:59 +0100 Subject: Add Python3 support --- pcilib/py.c | 56 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 14 deletions(-) (limited to 'pcilib') diff --git a/pcilib/py.c b/pcilib/py.c index 699cd59..b8f4800 100644 --- a/pcilib/py.c +++ b/pcilib/py.c @@ -49,8 +49,21 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag gstate = PyGILState_Ensure(); if (PyErr_Occurred()) { PyErr_Fetch(&pytype, &pyval, &pytraceback); - type = PyString_AsString(pytype); - val = PyString_AsString(pyval); + +#if PY_MAJOR_VERSION >= 3 + type = PyUnicode_AsUTF8(pytype); + val = PyUnicode_AsUTF8(pyval); +#else /*PY_MAJOR_VERSION >= 3*/ + PyObject *buf = PyUnicode_AsASCIIString(pytype); + type = PyString_AsString(buf); + Py_DecRef(buf); + + buf = PyUnicode_AsASCIIString(pyval); + val = PyString_AsString(buf); + Py_DecRef(buf); +#endif /*PY_MAJOR_VERSION >= 3*/ + + } PyGILState_Release(gstate); #endif /* HAVE_PYTHON */ @@ -101,7 +114,7 @@ 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 work 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->finalyze = 1; @@ -125,8 +138,9 @@ int pcilib_init_py(pcilib_t *ctx) { return PCILIB_ERROR_FAILED; } - PyObject *mod_name = PyString_FromString("Pcilib"); - PyObject *pyctx = PyCObject_FromVoidPtr(ctx, NULL); + PyObject *mod_name = PyUnicode_FromString("Pcilib"); + PyObject *pyctx = PyCapsule_New(ctx, "pcilib", NULL); + ctx->py->pcilib_pywrap = PyObject_CallMethodObjArgs(pywrap, mod_name, pyctx, NULL); Py_XDECREF(pyctx); Py_XDECREF(mod_name); @@ -166,7 +180,8 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) { return PCILIB_ERROR_FAILED; } - pynewdir = PyString_FromString(script_dir); + pynewdir = PyUnicode_FromString(script_dir); + if (!pynewdir) { pcilib_python_error("Can't create python string"); return PCILIB_ERROR_MEMORY; @@ -175,13 +190,13 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) { // Checking if the directory already in the path pydict = PyDict_New(); if (pydict) { - pystr = PyString_FromString("cur"); + pystr = PyUnicode_FromString("cur"); if (pystr) { PyDict_SetItem(pydict, pystr, pynewdir); Py_DECREF(pystr); } - pystr = PyString_FromString("path"); + pystr = PyUnicode_FromString("path"); if (pystr) { PyDict_SetItem(pydict, pystr, pypath); Py_DECREF(pystr); @@ -292,13 +307,13 @@ int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char *script_ return PCILIB_ERROR_FAILED; } - pystr = PyString_FromString("read_from_register"); + pystr = PyUnicode_FromString("read_from_register"); if (pystr) { if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_R; Py_DECREF(pystr); } - pystr = PyString_FromString("write_to_register"); + pystr = PyUnicode_FromString("write_to_register"); if (pystr) { if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_W; Py_DECREF(pystr); @@ -322,7 +337,7 @@ pcilib_py_object *pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *va switch(val->type) { case PCILIB_TYPE_LONG: ival = pcilib_get_value_as_int(ctx, val, &err); - if (!err) res = (PyObject*)PyInt_FromLong(ival); + if (!err) res = (PyObject*)PyLong_FromLong(ival); break; case PCILIB_TYPE_DOUBLE: fval = pcilib_get_value_as_float(ctx, val, &err); @@ -359,12 +374,25 @@ int pcilib_set_value_from_pyobject(pcilib_t* ctx, pcilib_value_t *val, pcilib_py PyGILState_STATE gstate; gstate = PyGILState_Ensure(); +#if PY_MAJOR_VERSION < 3 if (PyInt_Check(pyval)) { - err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyval)); + err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyval)); + } else if (PyString_Check(pyval)) { + err = pcilib_set_value_from_string(ctx, val, PyString_AsString(pyval)); + } else +#endif /*PY_MAJOR_VERSION >= 3*/ + if (PyLong_Check(pyval)) { + err = pcilib_set_value_from_int(ctx, val, PyLong_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 if (PyUnicode_Check(pyval)) { +#if PY_MAJOR_VERSION >= 3 + err = pcilib_set_value_from_string(ctx, val, PyUnicode_AsUTF8(pyval)); +#else /*PY_MAJOR_VERSION >= 3*/ + PyObject *buf = PyUnicode_AsASCIIString(pyval); + err = pcilib_set_value_from_string(ctx, val, PyString_AsString(buf)); + Py_DecRef(buf); +#endif /*PY_MAJOR_VERSION >= 3*/ } else { PyGILState_Release(gstate); pcilib_error("Can't convert PyObject to polymorphic pcilib value"); -- cgit v1.2.3