annotate Sources/PythonLock.cpp @ 20:5466d9340fc7

merge
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 01 Apr 2020 11:01:20 +0200
parents 952e969a2240
children b2bbb516056e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
1 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
2 * Python plugin for Orthanc
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
3 * Copyright (C) 2017-2020 Osimis S.A., Belgium
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
4 *
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
5 * This program is free software: you can redistribute it and/or
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
6 * modify it under the terms of the GNU Affero General Public License
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
7 * as published by the Free Software Foundation, either version 3 of
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
8 * the License, or (at your option) any later version.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
9 *
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
10 * This program is distributed in the hope that it will be useful, but
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
13 * Affero General Public License for more details.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
14 *
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
15 * You should have received a copy of the GNU Affero General Public License
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
17 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
18
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
19
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
20 #include "PythonLock.h"
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
21
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
22 #include "PythonFunction.h"
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
23 #include "PythonModule.h"
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
24
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
25 #include <OrthancPluginCppWrapper.h>
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
26
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
27 #include <boost/thread/mutex.hpp>
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
28
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
29 static boost::mutex mutex_;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
30 static PyThreadState* interpreterState_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
31 static PythonLock::ModuleFunctionsInstaller moduleFunctions_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
32 static PythonLock::ModuleClassesInstaller moduleClasses_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
33 static std::string moduleName_;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
34 static std::string exceptionName_;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
35
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
36
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
37 struct module_state
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
38 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
39 PyObject *exceptionClass_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
40 };
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
41
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
42 #if PY_MAJOR_VERSION >= 3
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
43 # define GETSTATE(module) ((struct module_state*) PyModule_GetState(module))
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
44 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
45 # define GETSTATE(module) (&_state)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
46 static struct module_state _state;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
47 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
48
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
49
13
952e969a2240 cppcheck
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 12
diff changeset
50 PythonLock::PythonLock() :
952e969a2240 cppcheck
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 12
diff changeset
51 gstate_(PyGILState_Ensure())
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
52 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
53 //OrthancPlugins::LogInfo("Python lock (GIL) acquired");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
54 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
55
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
56
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
57 PythonLock::~PythonLock()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
58 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
59 PyGILState_Release(gstate_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
60 //OrthancPlugins::LogInfo("Python lock (GIL) released");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
61 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
62
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
63
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
64 void PythonLock::ExecuteCommand(const std::string& s)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
65 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
66 if (PyRun_SimpleString(s.c_str()) != 0)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
67 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
68 OrthancPlugins::LogError("Error while executing a Python command");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
69 ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
70 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
71 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
72
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
73
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
74 void PythonLock::ExecuteFile(const std::string& path)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
75 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
76 OrthancPlugins::MemoryBuffer buffer;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
77 buffer.ReadFile(path);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
78
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
79 std::string script;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
80 buffer.ToString(script);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
81
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
82 ExecuteCommand(script);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
83 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
84
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
85
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
86 bool PythonLock::HasErrorOccurred(std::string& target)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
87 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
88 if (PyErr_Occurred())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
89 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
90 PyObject *exceptionType = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
91 PyObject *exceptionValue = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
92 PyObject *traceback = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
93 PyErr_Fetch(&exceptionType, &exceptionValue, &traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
94
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
95 if (exceptionType == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
96 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
97 return false;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
98 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
99
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
100 PyErr_NormalizeException(&exceptionType, &exceptionValue, &traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
101
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
102 #if PY_MAJOR_VERSION >= 3
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
103 if (traceback != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
104 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
105 PyException_SetTraceback(exceptionValue, traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
106 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
107 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
108
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
109 if (exceptionType != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
110 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
111 PythonObject temp(*this, PyObject_Str(exceptionType));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
112 std::string s;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
113 if (temp.ToUtf8String(s))
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
114 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
115 target += s + "\n";
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
116 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
117 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
118
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
119 if (exceptionValue != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
120 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
121 PythonObject temp(*this, PyObject_Str(exceptionValue));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
122 std::string s;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
123 if (temp.ToUtf8String(s))
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
124 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
125 target += s + "\n";
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
126 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
127 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
128
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
129 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
130 PythonModule module(*this, "traceback");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
131 PythonFunction f(*this, module, "format_tb");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
132
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
133 if (traceback != NULL &&
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
134 f.IsValid())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
135 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
136 PythonObject args(*this, PyTuple_New(1));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
137 PyTuple_SetItem(args.GetPyObject(), 0, traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
138
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
139 std::auto_ptr<PythonObject> value(f.CallUnchecked(args.GetPyObject()));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
140
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
141 if (value->IsValid())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
142 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
143 Py_ssize_t len = PyList_Size(value->GetPyObject());
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
144 for (Py_ssize_t i = 0; i < len; i++)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
145 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
146 PythonObject item(*this, PyList_GetItem(value->GetPyObject(), i), true /* borrowed */);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
147 std::string line;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
148 if (item.ToUtf8String(line))
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
149 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
150 target += "\n" + line;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
151 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
152 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
153 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
154 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
155 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
156
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
157
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
158 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
159 * "This call takes away a reference to each object: you must own
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
160 * a reference to each object before the call and after the call
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
161 * you no longer own these references. (If you don't understand
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
162 * this, don't use this function. I warned you.)"
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
163 * => I don't use PyErr_Restore()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
164 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
165
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
166 //PyErr_Restore(exceptionType, exceptionValue, traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
167 //PyErr_Clear();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
168
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
169 return true;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
170 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
171 else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
172 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
173 return false;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
174 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
175 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
176
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
177
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
178 static void RegisterException(PyObject* module,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
179 const std::string& name)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
180 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
181 struct module_state *state = GETSTATE(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
182
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
183 state->exceptionClass_ = PyErr_NewException(const_cast<char*>(name.c_str()), NULL, NULL);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
184 if (state->exceptionClass_ == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
185 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
186 Py_DECREF(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
187 OrthancPlugins::LogError("Cannot create the Python exception class");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
188 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
189 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
190
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
191 #if 1
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
192 Py_XINCREF(state->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
193 if (PyModule_AddObject(module, "Exception", state->exceptionClass_) < 0)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
194 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
195 Py_XDECREF(state->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
196 Py_CLEAR(state->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
197 OrthancPlugins::LogError("Cannot create the Python exception class");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
198 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
199 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
200 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
201 // Install the exception class
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
202 PyObject* dict = PyModule_GetDict(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
203 PyDict_SetItemString(dict, "Exception", state->exceptionClass);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
204 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
205 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
206
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
207
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
208
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
209 #if PY_MAJOR_VERSION >= 3
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
210
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
211 static int sdk_traverse(PyObject *module, visitproc visit, void *arg)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
212 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
213 Py_VISIT(GETSTATE(module)->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
214 return 0;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
215 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
216
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
217 static int sdk_clear(PyObject *module)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
218 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
219 Py_CLEAR(GETSTATE(module)->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
220 return 0;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
221 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
222
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
223 static struct PyModuleDef moduledef =
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
224 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
225 PyModuleDef_HEAD_INIT,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
226 NULL, /* m_name => TO BE FILLED */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
227 NULL,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
228 sizeof(struct module_state),
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
229 NULL, /* m_methods => TO BE FILLED */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
230 NULL,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
231 sdk_traverse,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
232 sdk_clear,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
233 NULL
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
234 };
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
235
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
236
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
237 PyMODINIT_FUNC InitializeModule()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
238 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
239 if (moduleFunctions_ == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
240 moduleClasses_ == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
241 moduleName_.empty() ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
242 exceptionName_.empty())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
243 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
244 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
245 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
246
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
247 moduledef.m_name = moduleName_.c_str();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
248 moduledef.m_methods = moduleFunctions_();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
249
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
250 PyObject *module = PyModule_Create(&moduledef);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
251 if (module == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
252 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
253 OrthancPlugins::LogError("Cannot create a Python module");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
254 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
255 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
256
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
257 RegisterException(module, moduleName_ + "." + exceptionName_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
258 moduleClasses_(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
259
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
260 return module;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
261 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
262
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
263 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
264
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
265 void InitializeModule()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
266 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
267 if (moduleFunctions_ == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
268 moduleClasses_ == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
269 moduleName_.empty() ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
270 exceptionName_.empty())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
271 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
272 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
273 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
274
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
275 PyObject *module = Py_InitModule(moduleName_.c_str(), moduleFunctions_());
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
276 if (module == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
277 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
278 OrthancPlugins::LogError("Cannot create a Python module");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
279 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
280 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
281
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
282 RegisterException(module, moduleName_ + "." + exceptionName_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
283 moduleClasses_(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
284 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
285
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
286 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
287
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
288
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
289
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
290 void PythonLock::GlobalInitialize(const std::string& moduleName,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
291 const std::string& exceptionName,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
292 ModuleFunctionsInstaller moduleFunctions,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
293 ModuleClassesInstaller moduleClasses,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
294 bool verbose)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
295 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
296 boost::mutex::scoped_lock lock(mutex_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
297
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
298 if (interpreterState_ != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
299 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
300 OrthancPlugins::LogError("Cannot initialize twice the Python interpreter");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
301 ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
302 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
303
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
304 if (moduleClasses == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
305 moduleFunctions == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
306 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
307 ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
308 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
309
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
310 if (moduleName.empty() ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
311 exceptionName.empty())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
312 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
313 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
314 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
315
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
316 if (exceptionName.find('.') != std::string::npos)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
317 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
318 OrthancPlugins::LogError("The name of the exception cannot contain \".\", found: " +
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
319 exceptionName);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
320 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
321 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
322
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
323 moduleClasses_ = moduleClasses;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
324 moduleFunctions_ = moduleFunctions;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
325 moduleName_ = moduleName;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
326 exceptionName_ = exceptionName;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
327
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
328 std::string executable;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
329
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
330 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
331 OrthancPlugins::OrthancString str;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
332 str.Assign(OrthancPluginGetOrthancPath(OrthancPlugins::GetGlobalContext()));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
333 str.ToString(executable);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
334 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
335
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
336 OrthancPlugins::LogWarning("Program name: " + executable);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
337
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
338 #if PY_MAJOR_VERSION == 2
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
339 Py_SetProgramName(&executable[0]); /* optional but recommended */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
340 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
341 std::wstring wide(executable.begin(), executable.end());
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
342 Py_SetProgramName(&wide[0]); /* optional but recommended */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
343 Py_UnbufferedStdioFlag = 1; // Write immediately to stdout after "sys.stdout.flush()" (only in Python 3.x)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
344 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
345
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
346 Py_InspectFlag = 1; // Don't exit the Orthanc process on Python error
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
347
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
348 if (verbose)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
349 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
350 Py_VerboseFlag = 1;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
351 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
352
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
353 #if PY_MAJOR_VERSION >= 3
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
354 PyImport_AppendInittab(moduleName_.c_str(), InitializeModule);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
355 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
356
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
357 #if PY_VERSION_HEX < 0x03020000 /* 3.2.0 */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
358 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
359 * "Changed in version 3.2: This function cannot be called before
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
360 * Py_Initialize() anymore."
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
361 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
362 if (!PyEval_ThreadsInitialized())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
363 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
364 PyEval_InitThreads();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
365 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
366 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
367
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
368 Py_InitializeEx(0 /* Python is embedded, skip signal handlers */);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
369
12
0b8239ce1bec removed debug logs
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 0
diff changeset
370 #if 0
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
371 #if PY_MAJOR_VERSION == 2
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
372 std::cout << Py_GetPath() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
373 std::cout << Py_GetProgramName() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
374 std::cout << Py_GetProgramFullPath() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
375 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
376 std::wcout << Py_GetPath() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
377 std::wcout << Py_GetProgramName() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
378 std::wcout << Py_GetProgramFullPath() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
379 #endif
12
0b8239ce1bec removed debug logs
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 0
diff changeset
380 #endif
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
381
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
382 #if (PY_VERSION_HEX >= 0x03020000 /* 3.2.0 */ && \
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
383 PY_VERSION_HEX < 0x03070000 /* 3.7.0 */)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
384 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
385 * Changed in version 3.7: This function is now called by
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
386 * Py_Initialize(), so you don't have to call it yourself anymore.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
387 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
388 if (!PyEval_ThreadsInitialized())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
389 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
390 PyEval_InitThreads();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
391 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
392 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
393
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
394
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
395 #if PY_MAJOR_VERSION == 2
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
396 InitializeModule();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
397 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
398
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
399 // https://fr.slideshare.net/YiLungTsai/embed-python => slide 26
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
400 interpreterState_ = PyEval_SaveThread();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
401 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
402
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
403
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
404 void PythonLock::AddSysPath(const std::string& path)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
405 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
406 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
407 * "It is recommended that applications embedding the Python
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
408 * interpreter for purposes other than executing a single script
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
409 * pass 0 as updatepath, and update sys.path themselves if
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
410 * desired. See CVE-2008-5983."
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
411 * => Set "sys.path.append()" to the directory of the configuration file by default
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
412 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
413
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
414 PythonLock lock;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
415
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
416 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
417 * Initialization of "sys.path.append()" must be done before loading
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
418 * any module.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
419 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
420
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
421 PyObject *sysPath = PySys_GetObject(const_cast<char*>("path"));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
422 if (sysPath == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
423 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
424 OrthancPlugins::LogError("Cannot find sys.path");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
425 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
426 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
427
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
428 PyObject* pyPath = PyUnicode_FromString(path.c_str());
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
429 int result = PyList_Insert(sysPath, 0, pyPath);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
430 Py_DECREF(pyPath);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
431
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
432 if (result != 0)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
433 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
434 OrthancPlugins::LogError("Cannot run sys.path.append()");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
435 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
436 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
437 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
438
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
439
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
440 void PythonLock::GlobalFinalize()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
441 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
442 boost::mutex::scoped_lock lock(mutex_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
443
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
444 if (interpreterState_ != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
445 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
446 PyEval_RestoreThread(interpreterState_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
447 interpreterState_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
448 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
449
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
450 Py_Finalize();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
451 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
452
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
453
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
454 void PythonLock::RaiseException(PyObject* module,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
455 OrthancPluginErrorCode code)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
456 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
457 if (code != OrthancPluginErrorCode_Success)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
458 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
459 const char* message = OrthancPluginGetErrorDescription(OrthancPlugins::GetGlobalContext(), code);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
460
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
461 struct module_state *state = GETSTATE(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
462 if (state->exceptionClass_ == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
463 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
464 OrthancPlugins::LogError("No Python exception has been registered");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
465 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
466 else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
467 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
468 PyErr_SetString(state->exceptionClass_, message);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
469 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
470 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
471 }