/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool
354 by Suren A. Chilingaryan
Stabilize merged code
1
#include "config.h"
2
3
#ifdef HAVE_PYTHON
4
# include <Python.h>
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
5
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
6
# if PY_MAJOR_VERSION >= 3
7
#  include <pthread.h>
8
# endif /* PY_MAJOR_VERSION >= 3 */
354 by Suren A. Chilingaryan
Stabilize merged code
9
#endif /* HAVE_PYTHON */
10
309 by Suren A. Chilingaryan
Base functions for views
11
#include <stdio.h>
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
12
#include <stdlib.h>
309 by Suren A. Chilingaryan
Base functions for views
13
#include <string.h>
14
#include <strings.h>
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
15
#include <alloca.h>
309 by Suren A. Chilingaryan
Base functions for views
16
17
#include "pci.h"
314 by Suren A. Chilingaryan
Support writting register views
18
#include "debug.h"
309 by Suren A. Chilingaryan
Base functions for views
19
#include "pcilib.h"
20
#include "py.h"
21
#include "error.h"
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
22
23
#ifdef HAVE_PYTHON
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
24
# define PCILIB_PYTHON_WRAPPER "pcipywrap"
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
25
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
26
typedef struct pcilib_script_s pcilib_script_t;
27
28
struct pcilib_script_s {
29
    const char *name;			/**< Script name */
30
    PyObject *module;			/**< PyModule object, contains script enviroment */	
31
    UT_hash_handle hh;			/**< hash */
32
};
346.1.10 by Vasilii Chernov
1. Cmakelists - move copy xml folder command to root file
33
309 by Suren A. Chilingaryan
Base functions for views
34
struct pcilib_py_s {
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
35
    int finalyze; 			/**< Indicates, that we are initialized from wrapper and should not destroy Python resources in destructor */
36
    PyObject *main_module;		/**< Main interpreter */
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
37
    PyObject *pywrap_module;		/**< Pcilib python wrapper */
38
    PyObject *threading_module;		/**< Threading module */
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
39
    PyObject *global_dict;		/**< Dictionary of main interpreter */
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
40
    PyObject *pcilib_pywrap;		/**< pcilib wrapper context */
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
41
    pcilib_script_t *script_hash;	/**< Hash with loaded scripts */
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
42
    
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
43
# if PY_MAJOR_VERSION >= 3
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
44
    int status;				/**< Indicates if python was initialized successfuly (0) or error have occured */
45
    pthread_t pth;			/**< Helper thread for Python initialization */
46
    pthread_cond_t cond;		/**< Condition informing about initialization success and request for clean-up */
47
    pthread_mutex_t lock;		/**< Condition lock */
48
49
//    PyInterpreterState *istate;
50
//    PyThreadState *tstate;
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
51
# endif /* PY_MAJOR_VERSION > 3 */
309 by Suren A. Chilingaryan
Base functions for views
52
};
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
53
#endif /* HAVE_PYTHON */
54
55
void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flags, pcilib_log_priority_t prio, const char *msg, ...) {
56
    va_list va;
57
    const char *type = NULL;
58
    const char *val = NULL;
59
60
#ifdef HAVE_PYTHON
354 by Suren A. Chilingaryan
Stabilize merged code
61
    PyGILState_STATE gstate;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
62
    PyObject *pytype = NULL;
63
    PyObject *pyval = NULL;
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
64
    PyObject *pystr = NULL;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
65
    PyObject *pytraceback = NULL;
66
354 by Suren A. Chilingaryan
Stabilize merged code
67
68
    gstate = PyGILState_Ensure();
69
    if (PyErr_Occurred()) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
70
	PyErr_Fetch(&pytype, &pyval, &pytraceback);
71
	PyErr_NormalizeException(&pytype, &pyval, &pytraceback);
72
	if (pyval) pystr = PyObject_Str(pyval);
346.1.35 by Vasilii Chernov
Add Python3 support
73
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
74
# if PY_MAJOR_VERSION >= 3
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
75
	if (pytype) {
76
	    if (PyUnicode_Check(pytype))
77
		type = PyUnicode_AsUTF8(pytype);
78
	    else
79
		type = PyExceptionClass_Name(pytype);
80
	}
81
	if (pystr) {
82
	    val = PyUnicode_AsUTF8(pystr);
83
	}
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
84
# else /* PY_MAJOR_VERSION >= 3 */
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
85
	if (pytype) {
86
	    if (PyString_Check(pytype))
87
		type = PyString_AsString(pytype);
88
	    else
89
		type = PyExceptionClass_Name(pytype);
90
	}
91
	if (pystr) {
92
	    val = PyString_AsString(pystr);
93
	}
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
94
# endif /*PY_MAJOR_VERSION >= 3*/
354 by Suren A. Chilingaryan
Stabilize merged code
95
    }
96
    PyGILState_Release(gstate);
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
97
#endif /* HAVE_PYTHON */
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
98
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
99
    va_start(va, msg);
100
    if (type) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
101
	char *str;
102
	size_t len = 32;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
103
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
104
	if (msg) len += strlen(msg);
105
	if (type) len += strlen(type);
106
	if (val) len += strlen(val);
107
	    
108
	str = alloca(len * sizeof(char));
109
	if (str) {
110
	    if (msg&&val)
111
		sprintf(str, "%s <%s: %s>", msg, type, val);
112
	    else if (msg)
113
		sprintf(str, "%s <%s>", msg, type);
114
	    else if (val)
115
		sprintf(str, "Python error %s: %s", type, val);
116
	    else
117
		sprintf(str, "Python error %s", type);
118
	    
119
	    pcilib_log_vmessage(file, line, flags, prio, str, va);
120
	}
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
121
    } else  {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
122
	pcilib_log_vmessage(file, line, flags, prio, msg, va);
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
123
    }
124
    va_end(va);
125
126
#ifdef HAVE_PYTHON
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
127
    if (pystr) Py_DECREF(pystr);
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
128
    if (pytype) Py_DECREF(pytype);
129
    if (pyval) Py_DECREF(pyval);
130
    if (pytraceback) Py_DECREF(pytraceback);
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
131
#endif /* HAVE_PYTHON */
132
}
133
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
134
#ifdef HAVE_PYTHON
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
135
static int pcilib_py_load_default_modules(pcilib_t *ctx) {
136
    PyGILState_STATE gstate = PyGILState_Ensure();
137
138
    ctx->py->main_module = PyImport_AddModule("__parser__");
139
    if (!ctx->py->main_module) {
140
	PyGILState_Release(gstate);
141
	pcilib_python_warning("Error importing python parser");
142
        return PCILIB_ERROR_FAILED;
143
    }
144
145
    ctx->py->global_dict = PyModule_GetDict(ctx->py->main_module);
146
    if (!ctx->py->global_dict) {
147
	PyGILState_Release(gstate);
148
	pcilib_python_warning("Error locating global python dictionary");
149
        return PCILIB_ERROR_FAILED;
150
    }
151
152
    ctx->py->pywrap_module = PyImport_ImportModule(PCILIB_PYTHON_WRAPPER);
153
    if (!ctx->py->pywrap_module) {
154
	PyGILState_Release(gstate);
155
	pcilib_python_warning("Error importing pcilib python wrapper");
156
	return PCILIB_ERROR_FAILED;
157
    }
158
159
    /**
160
     * We need to load threading module here, otherwise if any of the scripts
161
     * will use threading, on cleanup Python3 will complain:
162
     * Exception KeyError: KeyError(140702199305984,) in <module 'threading' from '/usr/lib64/python3.3/threading.py'> ignored
163
     * The idea to load threading module is inspired by
164
     * http://stackoverflow.com/questions/8774958/keyerror-in-module-threading-after-a-successful-py-test-run
165
     */
166
    ctx->py->threading_module = PyImport_ImportModule("threading");
167
    if (!ctx->py->threading_module) {
168
	PyGILState_Release(gstate);
169
	pcilib_python_warning("Error importing threading python module");
170
	return PCILIB_ERROR_FAILED;
171
    }
172
	
173
    PyObject *mod_name = PyUnicode_FromString(PCILIB_PYTHON_WRAPPER);
174
    PyObject *pyctx = PyCapsule_New(ctx, "pcilib", NULL);
175
    ctx->py->pcilib_pywrap = PyObject_CallMethodObjArgs(ctx->py->pywrap_module, mod_name, pyctx, NULL);
176
    Py_XDECREF(pyctx);
177
    Py_XDECREF(mod_name);
178
	
179
    if (!ctx->py->pcilib_pywrap) {
180
	PyGILState_Release(gstate);
181
	pcilib_python_warning("Error initializing python wrapper");
182
        return PCILIB_ERROR_FAILED;
183
    }
184
185
    PyGILState_Release(gstate);
186
    return 0;
187
}
188
189
static void pcilib_py_clean_default_modules(pcilib_t *ctx) {
190
    PyGILState_STATE gstate;
191
192
    gstate = PyGILState_Ensure();
193
194
    if (ctx->py->pcilib_pywrap) Py_DECREF(ctx->py->pcilib_pywrap);
195
196
    if (ctx->py->threading_module) Py_DECREF(ctx->py->threading_module);
197
    if (ctx->py->pywrap_module) Py_DECREF(ctx->py->pywrap_module);
198
199
	// Crashes Python2
200
//    if (ctx->py->main_module) Py_DECREF(ctx->py->main_module);
201
202
    PyGILState_Release(gstate);
203
}
204
205
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
206
# if PY_MAJOR_VERSION >= 3
207
/**
208
 * Python3 specially treats the main thread intializing Python. It crashes if
209
 * the Lock is released and any Python code is executed under the GIL compaling
210
 * that GIL is not locked. Python3 assumes that the main thread most of the time
211
 * holds the Lock, only shortly giving it away to other threads and re-obtaining 
212
 * it hereafter. This is not possible to do with GILs, but instead (probably)
213
 * PyEval_{Save,Restore}Thread() should be used. On other hand, the other threads
214
 * are working fine with GILs. This makes things complicated as we need to know
215
 * if we are running in main thread or not.
216
 * To simplify matters, during initalization we start a new thread which will
217
 * performa actual initialization of Python and, hence, act as main thread.
218
 * We only intialize here. No python code is executed afterwards. So we don't
219
 * need to care about special locking mechanisms in main thread. Instead all
220
 * our user threads can use GILs normally. 
221
 * See more details here:
222
 * http://stackoverflow.com/questions/24499393/cpython-locking-the-gil-in-the-main-thread
223
 * http://stackoverflow.com/questions/15470367/pyeval-initthreads-in-python-3-how-when-to-call-it-the-saga-continues-ad-naus
224
 */
225
static void *pcilib_py_run_init_thread(void *arg) {
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
226
    PyThreadState *state;
227
    pcilib_t *ctx = (pcilib_t*)arg;
228
    pcilib_py_t *py = ctx->py;
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
229
230
    Py_Initialize();
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
231
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
232
    PyEval_InitThreads();
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
233
234
//    state = PyThreadState_Get();
235
//    py->istate = state->interp;
236
237
    py->status = pcilib_py_load_default_modules(ctx);
238
239
    state = PyEval_SaveThread();
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
240
241
	// Ensure that main thread waiting for our signal
373 by Suren A. Chilingaryan
Fix compillation issues for Python3
242
    pthread_mutex_lock(&(py->lock));
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
243
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
244
	// Inform the parent thread that initialization is finished
245
    pthread_cond_signal(&(py->cond));
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
246
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
247
	// Wait untill cleanup is requested
248
    pthread_cond_wait(&(py->cond), &(py->lock));
373 by Suren A. Chilingaryan
Fix compillation issues for Python3
249
    pthread_mutex_unlock(&(py->lock));
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
250
251
    PyEval_RestoreThread(state);
252
    pcilib_py_clean_default_modules(ctx);
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
253
    Py_Finalize();
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
254
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
255
    return NULL;
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
256
}
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
257
# endif /* PY_MAJOR_VERSION < 3 */
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
258
#endif /* HAVE_PYTHON */
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
259
309 by Suren A. Chilingaryan
Base functions for views
260
int pcilib_init_py(pcilib_t *ctx) {
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
261
#ifdef HAVE_PYTHON
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
262
    int err = 0;
263
309 by Suren A. Chilingaryan
Base functions for views
264
    ctx->py = (pcilib_py_t*)malloc(sizeof(pcilib_py_t));
265
    if (!ctx->py) return PCILIB_ERROR_MEMORY;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
266
    memset(ctx->py, 0, sizeof(pcilib_py_t));
267
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
268
    if (!Py_IsInitialized()) {
269
# if PY_MAJOR_VERSION < 3
270
        Py_Initialize();
271
    	    // Since python is being initializing from c programm, it needs to initialize threads to work properly with c threads
272
        PyEval_InitThreads();
273
        PyEval_ReleaseLock();
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
274
275
	err = pcilib_py_load_default_modules(ctx);
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
276
# else /* PY_MAJOR_VERSION < 3 */
373 by Suren A. Chilingaryan
Fix compillation issues for Python3
277
	int err = pthread_mutex_init(&(ctx->py->lock), NULL);
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
278
	if (err) return PCILIB_ERROR_FAILED;
279
373 by Suren A. Chilingaryan
Fix compillation issues for Python3
280
	err = pthread_cond_init(&(ctx->py->cond), NULL);
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
281
	if (err) {
373 by Suren A. Chilingaryan
Fix compillation issues for Python3
282
	    pthread_mutex_destroy(&(ctx->py->lock));
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
283
	    return PCILIB_ERROR_FAILED;
284
	}
285
373 by Suren A. Chilingaryan
Fix compillation issues for Python3
286
	err = pthread_mutex_lock(&(ctx->py->lock));
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
287
	if (err) {
373 by Suren A. Chilingaryan
Fix compillation issues for Python3
288
	    pthread_cond_destroy(&(ctx->py->cond));
289
	    pthread_mutex_destroy(&(ctx->py->lock));
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
290
	    return PCILIB_ERROR_FAILED;
291
	}
292
293
	    // Create initalizer thread and wait until it releases the Lock
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
294
        err = pthread_create(&(ctx->py->pth), NULL, pcilib_py_run_init_thread, (void*)ctx);
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
295
	if (err) {
373 by Suren A. Chilingaryan
Fix compillation issues for Python3
296
	    pthread_mutex_unlock(&(ctx->py->lock));
297
	    pthread_cond_destroy(&(ctx->py->cond));
298
	    pthread_mutex_destroy(&(ctx->py->lock));
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
299
	    return PCILIB_ERROR_FAILED;
300
	}
301
302
    	    // Wait until initialized and keep the lock afterwards until free executed
373 by Suren A. Chilingaryan
Fix compillation issues for Python3
303
	pthread_cond_wait(&(ctx->py->cond), &(ctx->py->lock));
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
304
	err = ctx->py->status;
305
306
//	ctx->py->tstate =  PyThreadState_New(ctx->py->istate);
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
307
# endif /* PY_MAJOR_VERSION < 3 */
308
	ctx->py->finalyze = 1;
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
309
    } else {
310
	err = pcilib_py_load_default_modules(ctx);
311
    }
312
313
    if (err) {
314
	pcilib_free_py(ctx);
315
	return err;
316
    }
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
317
#endif /* HAVE_PYTHON */
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
318
346.1.16 by Vasilii Chernov
1. Add cmake BUILD_PYTHON_MODULES option.
319
    return 0;
320
}
321
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
322
void pcilib_free_py(pcilib_t *ctx) {
323
#ifdef HAVE_PYTHON
324
    if (ctx->py) {
325
	PyGILState_STATE gstate;
326
327
	gstate = PyGILState_Ensure();
328
	if (ctx->py->script_hash) {
329
	    pcilib_script_t *script, *script_tmp;
330
331
	    HASH_ITER(hh, ctx->py->script_hash, script, script_tmp) {
332
		Py_DECREF(script->module);
333
		HASH_DEL(ctx->py->script_hash, script);
334
		free(script);
335
	    }
336
	    ctx->py->script_hash = NULL;
337
	}
338
	PyGILState_Release(gstate);
339
340
#if PY_MAJOR_VERSION < 3
341
	pcilib_py_clean_default_modules(ctx);
342
#endif /* PY_MAJOR_VERSION < 3 */
343
344
	if (ctx->py->finalyze) {
345
#if PY_MAJOR_VERSION < 3
346
	    Py_Finalize();
347
#else /* PY_MAJOR_VERSION < 3 */
348
//	    PyThreadState_Delete(ctx->py->tstate);
349
350
		// singal python init thread to stop and wait it to finish
351
	    pthread_cond_signal(&(ctx->py->cond));
352
	    pthread_mutex_unlock(&(ctx->py->lock));
353
	    pthread_join(ctx->py->pth, NULL);
354
355
		// destroy synchronization primitives
356
	    pthread_cond_destroy(&(ctx->py->cond));
357
	    pthread_mutex_destroy(&(ctx->py->lock));
358
#endif /* PY_MAJOR_VERSION < 3 */
359
	}
360
        free(ctx->py);
361
        ctx->py = NULL;
362
    }
363
#endif /* HAVE_PYTHON */
364
}
365
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
366
int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) {
367
#ifdef HAVE_PYTHON
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
368
    int err = 0;
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
369
    PyObject *pypath, *pynewdir;
370
    PyObject *pydict, *pystr, *pyret = NULL;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
371
    char *script_dir;
372
369 by Suren A. Chilingaryan
Make Python problems non-fatal
373
    if (!ctx->py) return 0;
374
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
375
    const char *model_dir = getenv("PCILIB_MODEL_DIR");
376
    if (!model_dir) model_dir = PCILIB_MODEL_DIR;
377
378
    if (!dir) dir = ctx->model;
379
380
    if (*dir == '/') {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
381
	script_dir = (char*)dir;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
382
    } else {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
383
	script_dir = alloca(strlen(model_dir) + strlen(dir) + 2);
384
	if (!script_dir) return PCILIB_ERROR_MEMORY;
385
	sprintf(script_dir, "%s/%s", model_dir, dir);
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
386
    }
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
387
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
388
    PyGILState_STATE gstate = PyGILState_Ensure();
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
389
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
390
    pypath = PySys_GetObject("path");
391
    if (!pypath) {
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
392
	PyGILState_Release(gstate);
369 by Suren A. Chilingaryan
Make Python problems non-fatal
393
	pcilib_python_warning("Can't get python path");
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
394
	return PCILIB_ERROR_FAILED;
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
395
    }
396
346.1.35 by Vasilii Chernov
Add Python3 support
397
    pynewdir = PyUnicode_FromString(script_dir);
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
398
    if (!pynewdir) {
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
399
	PyGILState_Release(gstate);
369 by Suren A. Chilingaryan
Make Python problems non-fatal
400
	pcilib_python_warning("Can't create python string");
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
401
	return PCILIB_ERROR_MEMORY;
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
402
    }
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
403
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
404
    // Checking if the directory already in the path?
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
405
    pydict = PyDict_New();
406
    if (pydict) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
407
	pystr = PyUnicode_FromString("cur");
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
408
        if (pystr) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
409
	    PyDict_SetItem(pydict, pystr, pynewdir);
410
	    Py_DECREF(pystr);
411
	}
412
413
	pystr = PyUnicode_FromString("path");
414
	if (pystr) {
415
	    PyDict_SetItem(pydict, pystr, pypath);
416
	    Py_DECREF(pystr);
417
	}
418
419
	pyret = PyRun_String("cur in path", Py_eval_input, ctx->py->global_dict, pydict);
420
	Py_DECREF(pydict);
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
421
    } 
422
423
    if ((pyret == Py_False)&&(PyList_Append(pypath, pynewdir) == -1))
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
424
	err = PCILIB_ERROR_FAILED;
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
425
426
    if (pyret) Py_DECREF(pyret);
427
    Py_DECREF(pynewdir);
428
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
429
    PyGILState_Release(gstate);
430
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
431
    if (err) {
369 by Suren A. Chilingaryan
Make Python problems non-fatal
432
	pcilib_python_warning("Can't add directory (%s) to python path", script_dir);
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
433
	return err;
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
434
    }
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
435
#endif /* HAVE_PYTHON */
436
437
    return 0;
309 by Suren A. Chilingaryan
Base functions for views
438
}
439
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
440
441
int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) {
442
#ifdef HAVE_PYTHON
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
443
    PyObject* pymodule;
444
    pcilib_script_t *module = NULL;
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
445
    PyGILState_STATE gstate;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
446
369 by Suren A. Chilingaryan
Make Python problems non-fatal
447
    if (!ctx->py) return 0;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
448
449
    char *module_name = strdupa(script_name);
450
    if (!module_name) return PCILIB_ERROR_MEMORY;
451
452
    char *py = strrchr(module_name, '.');
453
    if ((!py)||(strcasecmp(py, ".py"))) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
454
	pcilib_error("Invalid script name (%s) is specified", script_name);
455
	return PCILIB_ERROR_INVALID_ARGUMENT;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
456
    }
457
    *py = 0;
458
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
459
    HASH_FIND_STR(ctx->py->script_hash, script_name, module);
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
460
    if (module) return 0;
461
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
462
    gstate = PyGILState_Ensure();
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
463
    pymodule = PyImport_ImportModule(module_name);
464
    if (!pymodule) {
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
465
	PyGILState_Release(gstate);
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
466
	pcilib_python_error("Error importing script (%s)", script_name);
467
	return PCILIB_ERROR_FAILED;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
468
    }
469
470
    module = (pcilib_script_t*)malloc(sizeof(pcilib_script_t));
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
471
    if (!module) {
472
	Py_DECREF(pymodule);
473
	PyGILState_Release(gstate);
474
	return PCILIB_ERROR_MEMORY;
475
    }
476
477
    PyGILState_Release(gstate);
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
478
479
    module->module = pymodule;
480
    module->name = script_name;
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
481
    HASH_ADD_KEYPTR(hh, ctx->py->script_hash, module->name, strlen(module->name), module);
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
482
#endif /* HAVE_PYTHON */
483
    return 0;
484
}
485
486
int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char *script_name, pcilib_access_mode_t *mode_ret) {
487
    pcilib_access_mode_t mode = 0;
488
489
#ifdef HAVE_PYTHON
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
490
    PyObject *dict;
491
    PyObject *pystr;
492
    pcilib_script_t *module;
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
493
    PyGILState_STATE gstate;
369 by Suren A. Chilingaryan
Make Python problems non-fatal
494
495
    if (!ctx->py) {
496
	if (mode_ret) *mode_ret = mode;
497
	return 0;
498
    }
499
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
500
    HASH_FIND_STR(ctx->py->script_hash, script_name, module);
501
502
    if(!module) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
503
	pcilib_error("Script (%s) is not loaded yet", script_name);
504
	return PCILIB_ERROR_NOTFOUND;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
505
    }
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
506
    
507
    gstate = PyGILState_Ensure();
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
508
	
509
    dict = PyModule_GetDict(module->module);
510
    if (!dict) {
372 by Suren A. Chilingaryan
Integrate last part of Python code from Vasiliy Chernov
511
	PyGILState_Release(gstate);
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
512
	pcilib_python_error("Error getting dictionary for script (%s)", script_name);
513
	return PCILIB_ERROR_FAILED;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
514
    }
515
    
346.1.35 by Vasilii Chernov
Add Python3 support
516
    pystr = PyUnicode_FromString("read_from_register");
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
517
    if (pystr) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
518
	if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_R;
519
	Py_DECREF(pystr);
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
520
    }
521
346.1.35 by Vasilii Chernov
Add Python3 support
522
    pystr = PyUnicode_FromString("write_to_register");
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
523
    if (pystr) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
524
	if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_W;
525
	Py_DECREF(pystr);
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
526
    }
346.1.38 by Vasilii Chernov
Fix python3 initialization from pcilib_t
527
    
528
    PyGILState_Release(gstate);
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
529
#endif /* HAVE_PYTHON */
530
375 by Suren A. Chilingaryan
Fix more threading problems in Python3
531
//    pcilib_py_load_default_modules(py->ctx);
532
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
533
    if (mode_ret) *mode_ret = mode;
534
    return 0;
535
}
536
537
pcilib_py_object *pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *val, int *ret) {
538
#ifdef HAVE_PYTHON	
539
    int err = 0;
540
    PyObject *res = NULL;
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
541
    PyGILState_STATE gstate;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
542
543
    long ival;
544
    double fval;
369 by Suren A. Chilingaryan
Make Python problems non-fatal
545
546
    if (!ctx->py) return NULL;
547
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
548
    gstate = PyGILState_Ensure();
549
    switch(val->type) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
550
     case PCILIB_TYPE_LONG:
551
	ival = pcilib_get_value_as_int(ctx, val, &err);
552
	if (!err) res = (PyObject*)PyLong_FromLong(ival);
553
	break;
554
     case PCILIB_TYPE_DOUBLE:
555
	fval = pcilib_get_value_as_float(ctx, val, &err);
556
	if (!err) res = (PyObject*)PyFloat_FromDouble(fval);
557
	break;	
558
     default:
559
	PyGILState_Release(gstate);
560
	pcilib_error("Can't convert pcilib value of type (%lu) to PyObject", val->type);
561
	if (ret) *ret = PCILIB_ERROR_NOTSUPPORTED;
562
	return NULL;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
563
    }
564
    PyGILState_Release(gstate);
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
565
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
566
    if (err) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
567
	if (ret) *ret = err;
568
	return NULL;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
569
    } else if (!res) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
570
	if (ret) *ret = PCILIB_ERROR_MEMORY;
571
	return res;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
572
    } 
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
573
574
    if (ret) *ret = 0;
575
    return res;
576
#else /* HAVE_PYTHON */
577
    pcilib_error("Python is not supported");
578
    return NULL;
579
#endif /* HAVE_PYTHON */
580
}
581
582
int pcilib_set_value_from_pyobject(pcilib_t* ctx, pcilib_value_t *val, pcilib_py_object *pval) {
583
#ifdef HAVE_PYTHON
584
    int err = 0;
585
    PyObject *pyval = (PyObject*)pval;
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
586
    PyGILState_STATE gstate;
369 by Suren A. Chilingaryan
Make Python problems non-fatal
587
588
    if (!ctx->py) return PCILIB_ERROR_NOTINITIALIZED;
589
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
590
    gstate = PyGILState_Ensure();
346.1.35 by Vasilii Chernov
Add Python3 support
591
    if (PyLong_Check(pyval)) {
592
        err = pcilib_set_value_from_int(ctx, val, PyLong_AsLong(pyval));
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
593
    } else if (PyFloat_Check(pyval)) {
594
        err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(pyval));
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
595
#if PY_MAJOR_VERSION < 3
596
    } else if (PyInt_Check(pyval)) {
597
        err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyval));
598
    } else if (PyString_Check(pyval)) {
599
        err = pcilib_set_value_from_string(ctx, val, PyString_AsString(pyval));
600
    } else if (PyUnicode_Check(pyval)) {
601
        PyObject *buf = PyUnicode_AsASCIIString(pyval);
602
        if (buf) {
603
    	    err = pcilib_set_value_from_string(ctx, val, PyString_AsString(buf));
604
    	    Py_DecRef(buf);
605
    	} else {
606
    	    err = PCILIB_ERROR_FAILED;
607
	}
608
#else /* PY_MAJOR_VERSION < 3 */
609
    } else if (PyUnicode_Check(pyval)) {
346.1.35 by Vasilii Chernov
Add Python3 support
610
        err = pcilib_set_value_from_string(ctx, val, PyUnicode_AsUTF8(pyval));
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
611
#endif /* PY_MAJOR_VERSION < 3 */
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
612
    } else {
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
613
        PyGILState_Release(gstate);
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
614
        pcilib_error("Can't convert PyObject to polymorphic pcilib value");
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
615
	return PCILIB_ERROR_NOTSUPPORTED;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
616
    }
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
617
    PyGILState_Release(gstate);
618
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
619
    return err;
620
#else /* HAVE_PYTHON */
621
    pcilib_error("Python is not supported");
622
    return PCILIB_ERROR_NOTSUPPORTED;
623
#endif /* HAVE_PYTHON */
624
}
625
626
#ifdef HAVE_PYTHON
309 by Suren A. Chilingaryan
Base functions for views
627
static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
628
    int i;
629
    int err = 0;
312 by Suren A. Chilingaryan
Support transform views
630
    pcilib_value_t val = {0};
309 by Suren A. Chilingaryan
Base functions for views
631
    pcilib_register_value_t regval;
632
633
    char save;
634
    char *reg, *cur;
635
    size_t offset = 0;
636
637
    size_t size;
638
    char *src;
639
    char *dst;
640
641
    size_t max_repl = 2 + 2 * sizeof(pcilib_value_t);                               // the text representation of largest integer
642
643
    if (value) {
644
        err = pcilib_copy_value(ctx, &val, value);
645
        if (err) return NULL;
646
647
        err = pcilib_convert_value_type(ctx, &val, PCILIB_TYPE_STRING);
648
        if (err) return NULL;
649
650
        if (strlen(val.sval) > max_repl)
651
            max_repl = strlen(val.sval);
652
    }
653
654
    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
655
656
    src = strdup(codestr);
657
    dst = (char*)malloc(size);                                                  // allocating maximum required space
658
659
    if ((!src)||(!dst)) {
660
        if (src) free(src);
661
        if (dst) free(dst);
662
        pcilib_error("Failed to allocate memory for string formulas");
663
        return NULL;
664
    }
665
666
    cur = src;
667
    reg = strchr(src, '$');
668
    while (reg) {
669
        strcpy(dst + offset, cur);
670
        offset += reg - cur;
671
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
672
            // find the end of the register name
309 by Suren A. Chilingaryan
Base functions for views
673
        reg++;
317 by Suren A. Chilingaryan
Support properties in transform formulas
674
        if (*reg == '{') {
675
            reg++;
676
            for (i = 0; (reg[i])&&(reg[i] != '}'); i++);
677
            if (!reg[i]) {
678
                pcilib_error("Python formula (%s) contains unterminated variable reference", codestr);
679
                err = PCILIB_ERROR_INVALID_DATA;
680
                break;
681
            }
682
        } else {
683
            for (i = 0; isalnum(reg[i])||(reg[i] == '_'); i++);
684
        }
309 by Suren A. Chilingaryan
Base functions for views
685
        save = reg[i];
686
        reg[i] = 0;
687
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
688
            // determine replacement value
309 by Suren A. Chilingaryan
Base functions for views
689
        if (!strcasecmp(reg, "value")) {
690
            if (!value) {
691
                pcilib_error("Python formula (%s) relies on the value of register, but it is not provided", codestr);
692
                err = PCILIB_ERROR_INVALID_REQUEST;
693
                break;
694
            }
695
696
            strcpy(dst + offset, val.sval);
697
        } else {
317 by Suren A. Chilingaryan
Support properties in transform formulas
698
            if (*reg == '/') {
699
                pcilib_value_t val = {0};
700
                err = pcilib_get_property(ctx, reg, &val);
701
                if (err) break;
702
                err = pcilib_convert_value_type(ctx, &val, PCILIB_TYPE_STRING);
703
                if (err) break;
704
                sprintf(dst + offset, "%s", val.sval);
705
            } else {
706
                err = pcilib_read_register(ctx, NULL, reg, &regval);
707
                if (err) break;
330 by Suren A. Chilingaryan
Support for 64-bit registes
708
                sprintf(dst + offset, "0x%lx", regval);
317 by Suren A. Chilingaryan
Support properties in transform formulas
709
            }
309 by Suren A. Chilingaryan
Base functions for views
710
        }
711
712
        offset += strlen(dst + offset);
317 by Suren A. Chilingaryan
Support properties in transform formulas
713
        if (save == '}') i++;
714
        else reg[i] = save;
309 by Suren A. Chilingaryan
Base functions for views
715
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
716
            // Advance to the next register if any
309 by Suren A. Chilingaryan
Base functions for views
717
        cur = reg + i;
718
        reg = strchr(cur, '$');
719
    }
720
721
    strcpy(dst + offset, cur);
722
723
    free(src);
724
725
    if (err) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
726
        free(dst);
727
        return NULL;
309 by Suren A. Chilingaryan
Base functions for views
728
    }
729
730
    return dst;
731
}
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
732
#endif /* HAVE_PYTHON */
309 by Suren A. Chilingaryan
Base functions for views
733
734
int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *value) {
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
735
#ifdef HAVE_PYTHON
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
736
    int err;
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
737
309 by Suren A. Chilingaryan
Base functions for views
738
    PyGILState_STATE gstate;
739
    char *code;
740
    PyObject* obj;
741
369 by Suren A. Chilingaryan
Make Python problems non-fatal
742
    if (!ctx->py) return PCILIB_ERROR_NOTINITIALIZED;
743
309 by Suren A. Chilingaryan
Base functions for views
744
    code = pcilib_py_parse_string(ctx, codestr, value);
745
    if (!code) {
746
        pcilib_error("Failed to parse registers in the code: %s", codestr);
747
        return PCILIB_ERROR_FAILED;
748
    }
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
749
309 by Suren A. Chilingaryan
Base functions for views
750
    gstate = PyGILState_Ensure();
751
    obj = PyRun_String(code, Py_eval_input, ctx->py->global_dict, ctx->py->global_dict);
752
    PyGILState_Release(gstate);
753
754
    if (!obj) {
755
        pcilib_error("Failed to run the Python code: %s", code);
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
756
        free(code);
309 by Suren A. Chilingaryan
Base functions for views
757
        return PCILIB_ERROR_FAILED;
758
    }
759
314 by Suren A. Chilingaryan
Support writting register views
760
    pcilib_debug(VIEWS, "Evaluating a Python string \'%s\' to %lf=\'%s\'", codestr, PyFloat_AsDouble(obj), code);
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
761
    err = pcilib_set_value_from_float(ctx, value, PyFloat_AsDouble(obj));
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
762
346.1.24 by Vasilii Chernov
Merge with Suren branch. Fix memory leaks.
763
    Py_DECREF(obj);
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
764
    free(code);
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
765
766
    return err;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
767
#else /* HAVE_PYTHON */
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
768
	pcilib_error("Current build not support python.");
346.1.16 by Vasilii Chernov
1. Add cmake BUILD_PYTHON_MODULES option.
769
    return PCILIB_ERROR_NOTAVAILABLE;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
770
#endif /* HAVE_PYTHON */
771
}
772
773
int pcilib_py_eval_func(pcilib_t *ctx, const char *script_name, const char *func_name, pcilib_value_t *val) {
774
#ifdef HAVE_PYTHON
775
    int err = 0;
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
776
    PyObject *pyfunc;
777
    PyObject *pyval = NULL, *pyret;
778
    pcilib_script_t *module = NULL;
779
369 by Suren A. Chilingaryan
Make Python problems non-fatal
780
    if (!ctx->py) return PCILIB_ERROR_NOTINITIALIZED;
781
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
782
    HASH_FIND_STR(ctx->py->script_hash, script_name, module);
783
784
    if (!module) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
785
	pcilib_error("Script (%s) is not loaded", script_name);
786
	return PCILIB_ERROR_NOTFOUND;
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
787
    }
346.1.29 by Vasilii Chernov
1. multithreading:
788
789
    if (val) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
790
	pyval = pcilib_get_value_as_pyobject(ctx, val, &err);
791
	if (err) return err;
346.1.29 by Vasilii Chernov
1. multithreading:
792
    }
793
356 by Suren A. Chilingaryan
Add more GILs to prevent Python crashes in multithreaded applications
794
    PyGILState_STATE gstate = PyGILState_Ensure();
795
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
796
    pyfunc = PyUnicode_FromString(func_name);
797
    if (!pyfunc) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
798
	if (pyval) Py_DECREF(pyval);
799
	PyGILState_Release(gstate);
800
	return PCILIB_ERROR_MEMORY;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
801
    }
802
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
803
    pyret = PyObject_CallMethodObjArgs(module->module, pyfunc, ctx->py->pcilib_pywrap, pyval, NULL);
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
804
357 by Suren A. Chilingaryan
Merge of further work on Python scripting from Vasiliy Chernov
805
    Py_DECREF(pyfunc);
806
    Py_DECREF(pyval);
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
807
	
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
808
    if (!pyret) {
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
809
	PyGILState_Release(gstate);
810
	pcilib_python_error("Error executing function (%s) of python script (%s)", func_name, script_name);
811
	return PCILIB_ERROR_FAILED;
346.1.29 by Vasilii Chernov
1. multithreading:
812
    }
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
813
814
    if ((val)&&(pyret != Py_None))
367 by Suren A. Chilingaryan
Further improvements of Python scripting and web-interface API for register manipulations by Vasiliy Chernov
815
	err = pcilib_set_value_from_pyobject(ctx, val, pyret);
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
816
817
    Py_DECREF(pyret);
346.1.29 by Vasilii Chernov
1. multithreading:
818
    PyGILState_Release(gstate);
346.1.33 by Vasilii Chernov
Move scripts handing code from py.c to Python wrap
819
820
    return err;
353 by Suren A. Chilingaryan
Merge Python scripting support from Vasiliy Chernov
821
#else /* HAVE_PYTHON */
822
    pcilib_error("Python is not supported");
823
    return PCILIB_ERROR_NOTSUPPORTED;
824
#endif /* HAVE_PYTHON */
346.1.6 by Vasilii Chernov
Merge script and transform view. Add get register and properties info to python wrap.
825
}