/
PythonWrapper.cpp
86 lines (68 loc) · 1.77 KB
/
PythonWrapper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "stdafx.h"
#include "PythonWrapper.h"
PythonWrapper::PythonWrapper()
{
Py_Initialize();
PyEval_InitThreads();
globals_ = bp::import(MAIN_MODULE).attr(DICT_ATTR);
mainThreadState_ = PyEval_SaveThread();
execFile(":/Python/Twitch", false);
execFile(":/Python/IRCParser", false);
qAddPostRoutine(clean);
}
PythonWrapper & PythonWrapper::instance()
{
static PythonWrapper pythonWrapper;
return pythonWrapper;
}
void PythonWrapper::clean()
{
auto & self = instance();
PyEval_RestoreThread(self.mainThreadState_);
self.globals_ = bp::object();
for(auto & thread : self.threads_)
if(thread.joinable()) thread.join();
Py_Finalize();
}
void PythonWrapper::exec(const PyFunctor & pyFunctor, bool concurrent)
{
auto & self = instance();
BindedPyFunctor bindedFunctor = std::bind(pyFunctor, self.globals_);
self.threads_.push_back(
std::thread(
std::bind(&PythonWrapper::execImpl, &self, bindedFunctor)));
if(!concurrent) self.threads_.rbegin()->join();
}
void PythonWrapper::exec(const QString & code, bool concurrent)
{
exec([&](const bp::object & globals)
{
bp::exec(code.toLocal8Bit().constData(), globals);
}, concurrent);
}
void PythonWrapper::execFile(const QString & fileName, bool concurrent)
{
QFile file(fileName);
if(file.open(QIODevice::ReadOnly))
exec(QString(file.readAll()), concurrent);
}
PythonWrapper::GILLocker::GILLocker()
{
state_ = PyGILState_Ensure();
}
PythonWrapper::GILLocker::~GILLocker()
{
PyGILState_Release(state_);
}
void PythonWrapper::execImpl(const BindedPyFunctor & functor)
{
GILLocker lock;
try
{
functor();
}
catch(const bp::error_already_set &)
{
PyErr_Print();
}
}