Skip to content

Commit 0228f3d

Browse files
committed
Initialize cpython on a separate thread, Rename include.hpp to pythoninclude.hpp, Catch exceptions in exprtkmodule.cpp module functions, Add thread state functions in interpreter.hpp
1 parent be1a8f2 commit 0228f3d

20 files changed

+623
-173
lines changed

CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ message("Python_Development_FOUND:${Python_Development_FOUND}")
1212
message("Python_LIBRARIES:${Python_LIBRARIES}")
1313
message("Python_INCLUDE_DIRS:${Python_INCLUDE_DIRS}")
1414

15+
find_package(Threads REQUIRED)
16+
1517
if (WIN32)
1618
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
1719
endif (WIN32)
@@ -64,3 +66,4 @@ target_link_libraries(qcalculator Qt5::Core Qt5::Widgets)
6466
target_link_libraries(qcalculator ${Python_LIBRARIES}) # Python
6567
target_link_libraries(qcalculator mpdec mpdec++) # mpdecimal
6668
target_link_libraries(qcalculator archive) # libarchive
69+
target_link_libraries(qcalculator Threads::Threads) # Threads

src/addon/addon.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,24 @@
2424

2525
#include "pycx/interpreter.hpp"
2626

27+
#include "util/interpreterhandler.hpp"
28+
2729
Addon::Addon(std::string moduleName, std::string displayName, std::string description)
2830
: loaded(false),
2931
moduleName(std::move(moduleName)),
3032
displayName(std::move(displayName)),
3133
description(std::move(description)) {}
3234

3335
void Addon::callFunctionNoArgs(const std::string &name) {
36+
if (!InterpreterHandler::waitForInitialization()) {
37+
throw std::runtime_error("Python is not initialized");
38+
}
3439
moduleLoaded = true;
3540
if (Interpreter::isInitialized()) {
3641
Interpreter::callFunctionNoArgs(moduleName + "." + moduleName, name);
3742
} else {
38-
throw std::runtime_error("Python is not initialized (The console contains the error message), ensure that the correct path is configured in the settings.");
43+
throw std::runtime_error(
44+
"Python is not initialized (The console contains the error message), ensure that the correct path is configured in the settings.");
3945
}
4046
}
4147

@@ -44,6 +50,10 @@ void Addon::reload() {
4450
if (l)
4551
unload();
4652

53+
if (!InterpreterHandler::waitForInitialization()) {
54+
throw std::runtime_error("Python is not initialized");
55+
}
56+
4757
if (Interpreter::isInitialized()) {
4858
Interpreter::reloadModule(moduleName + "." + moduleName);
4959
}

src/addon/addonmanager.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,13 @@ Archive AddonManager::createInstallableBundle(std::vector<InstallBundleEntry> en
160160
return archive;
161161
}
162162

163-
AddonManager::AddonManager(const std::string &addonDirectory,
163+
AddonManager::AddonManager(std::string addonDirectory,
164164
Listener onAddonLoadFail,
165165
Listener onAddonUnloadFail)
166-
: addonDir(addonDirectory),
166+
: addonDir(std::move(addonDirectory)),
167167
onAddonLoadFail(std::move(onAddonLoadFail)),
168168
onAddonUnloadFail(std::move(onAddonUnloadFail)) {
169-
reloadModules();
169+
readAddons();
170170
}
171171

172172
AddonManager::~AddonManager() {

src/addon/addonmanager.hpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ class AddonManager {
4545

4646
typedef std::function<void(const std::string &, const std::string &)> Listener;
4747

48-
AddonManager(const std::string &addonDirectory,
48+
AddonManager() = default;
49+
50+
AddonManager(std::string addonDirectory,
4951
Listener onAddonLoadFail,
5052
Listener onAddonUnloadFail);
5153

@@ -93,8 +95,9 @@ class AddonManager {
9395
* @param sourceFile
9496
* @param questionDialog
9597
*/
96-
size_t installAddonBundle(std::istream &sourceFile, const std::function<bool(const std::string &, const std::string &,
97-
std::vector<std::string> &)>& installDialog);
98+
size_t installAddonBundle(std::istream &sourceFile,
99+
const std::function<bool(const std::string &, const std::string &,
100+
std::vector<std::string> &)> &installDialog);
98101

99102

100103
void uninstallAddon(const std::string &moduleName);

src/main.cpp

+1-55
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,9 @@
1919

2020
#include <QApplication>
2121
#include <QMessageBox>
22-
#include <QProcess>
23-
2422
#include "windows/calculatorwindow.hpp"
2523

2624
#include "pycx/interpreter.hpp"
27-
#include "pycx/modules/stdredirmodule.hpp"
28-
#include "pycx/modules/exprtkmodule.hpp"
2925

3026
#include "io/paths.hpp"
3127
#include "io/fileoperations.hpp"
@@ -41,54 +37,6 @@ std::vector<std::string> parseArgs(int argc, char *argv[]) {
4137
return ret;
4238
}
4339

44-
std::wstring getUserPythonPath(Settings &settings) {
45-
std::string str;
46-
47-
if (settings.check(SETTING_PYTHON_PATH.key)) {
48-
str = settings.value(SETTING_PYTHON_PATH.key).toString();
49-
}
50-
51-
if (str.empty()) {
52-
return {};
53-
} else {
54-
std::wstring wret;
55-
for (auto &c: str) {
56-
wret += c;
57-
}
58-
return wret;
59-
}
60-
}
61-
62-
bool checkPythonInit(std::string &stdErr) {
63-
QProcess proc;
64-
proc.start(QApplication::applicationFilePath(), {"--run_python_init_check"}, QIODevice::ReadOnly);
65-
proc.waitForFinished();
66-
auto ret = proc.exitCode();
67-
stdErr = proc.readAllStandardError().toStdString();
68-
return !ret;
69-
}
70-
71-
std::string configurePython() {
72-
auto settings = Settings::readSettings();
73-
auto pythonPath = getUserPythonPath(settings);
74-
75-
std::string stdErr;
76-
77-
if (checkPythonInit(stdErr)) {
78-
if (!pythonPath.empty()) {
79-
Interpreter::setPath(pythonPath);
80-
}
81-
82-
StdRedirModule::initialize();
83-
ExprtkModule::initialize();
84-
Interpreter::initialize();
85-
Interpreter::addModuleDir(Paths::getLibDirectory());
86-
Interpreter::addModuleDir(Paths::getAddonDirectory());
87-
}
88-
89-
return stdErr;
90-
}
91-
9240
int runPythonInitCheck() {
9341
auto settings = Settings::readSettings();
9442
if (settings.check(SETTING_PYTHON_PATH.key)) {
@@ -123,8 +71,6 @@ int main(int argc, char *argv[]) {
12371
return runPythonInitCheck();
12472
}
12573

126-
auto err = configurePython();
127-
12874
if (args.size() > 1) {
12975
if (args.at(1) == "--interpreter" || args.at(1) == "-i") {
13076
// Run the application as an interactive python interpreter
@@ -139,7 +85,7 @@ int main(int argc, char *argv[]) {
13985
return 0;
14086
}
14187
} else {
142-
CalculatorWindow w((err).c_str());
88+
CalculatorWindow w;
14389
w.show();
14490
return QApplication::exec();
14591
}

src/math/scripthandler.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,17 @@
1919

2020
#include "math/scripthandler.hpp"
2121

22-
#include "pycx/include.hpp"
22+
#include "pycx/pythoninclude.hpp"
2323
#include "pycx/interpreter.hpp"
2424

25+
#include "util/interpreterhandler.hpp"
26+
2527
decimal::Decimal ScriptHandler::run(PyObject *c, const std::vector<decimal::Decimal> &a) {
26-
if (!Interpreter::isInitialized()){
28+
if (!InterpreterHandler::waitForInitialization()) {
29+
throw std::runtime_error("Python is not initialized");
30+
}
31+
32+
if (!Interpreter::isInitialized()) {
2733
throw std::runtime_error("Python is not initialized.");
2834
}
2935

0 commit comments

Comments
 (0)