mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
Remove support for external Python.
This commit is contained in:
+91
-220
@@ -26,172 +26,86 @@ along with python proxy plugin. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QWidget>
|
||||
#include <QMessageBox>
|
||||
#include <QCoreApplication>
|
||||
#include "resource.h"
|
||||
#include "log.h"
|
||||
|
||||
using namespace MOBase;
|
||||
|
||||
|
||||
const char *ProxyPython::s_DownloadPythonURL = "http://www.python.org/download/releases/";
|
||||
|
||||
|
||||
HMODULE GetOwnModuleHandle()
|
||||
{
|
||||
HMODULE hMod = nullptr;
|
||||
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
reinterpret_cast<LPCWSTR>(&GetOwnModuleHandle), &hMod);
|
||||
|
||||
return hMod;
|
||||
}
|
||||
|
||||
|
||||
QString ExtractResource(WORD resourceID, const QString &szFilename)
|
||||
{
|
||||
HMODULE mod = GetOwnModuleHandle();
|
||||
|
||||
HRSRC hResource = FindResourceW(mod, MAKEINTRESOURCE(resourceID), L"BINARY");
|
||||
if (hResource == nullptr) {
|
||||
throw Exception("embedded dll not available: " + windowsErrorString(::GetLastError()));
|
||||
}
|
||||
|
||||
HGLOBAL hFileResource = LoadResource(mod, hResource);
|
||||
if (hFileResource == nullptr) {
|
||||
throw Exception("failed to load embedded dll resource: " + windowsErrorString(::GetLastError()));
|
||||
}
|
||||
|
||||
LPVOID lpFile = LockResource(hFileResource);
|
||||
if (lpFile == nullptr) {
|
||||
throw Exception(QString("failed to lock resource: %1").arg(windowsErrorString(::GetLastError())));
|
||||
}
|
||||
|
||||
DWORD dwSize = SizeofResource(mod, hResource);
|
||||
|
||||
QString outFile = QDir::tempPath() + "/" + szFilename;
|
||||
|
||||
HANDLE hFile = CreateFileW(outFile.toStdWString().c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
if (::GetLastError() == ERROR_SHARING_VIOLATION) {
|
||||
// dll exists and is opened by another instance of MO, shouldn't be outdated then...
|
||||
return outFile;
|
||||
} else {
|
||||
throw Exception(QString("failed to open python runner: %1").arg(windowsErrorString(::GetLastError())));
|
||||
}
|
||||
}
|
||||
HANDLE hFileMap = CreateFileMapping(hFile, nullptr, PAGE_READWRITE, 0, dwSize, nullptr);
|
||||
if (hFileMap == NULL) {
|
||||
throw Exception(QString("failed to map python runner: %1").arg(windowsErrorString(::GetLastError())));
|
||||
}
|
||||
LPVOID lpAddress = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
|
||||
if (lpAddress == nullptr) {
|
||||
throw Exception(QString("failed to map view of file: %1").arg(windowsErrorString(::GetLastError())));
|
||||
}
|
||||
|
||||
CopyMemory(lpAddress, lpFile, dwSize);
|
||||
|
||||
UnmapViewOfFile(lpAddress);
|
||||
|
||||
CloseHandle(hFileMap);
|
||||
::FlushFileBuffers(hFile);
|
||||
CloseHandle(hFile);
|
||||
|
||||
return outFile;
|
||||
}
|
||||
|
||||
|
||||
ProxyPython::ProxyPython()
|
||||
: m_MOInfo(nullptr), m_Runner(nullptr), m_LoadFailure(FAIL_NOTINIT)
|
||||
: m_MOInfo{ nullptr },
|
||||
m_RunnerLib{ nullptr },
|
||||
m_Runner{ nullptr },
|
||||
m_LoadFailure(FailureType::NONE)
|
||||
{
|
||||
}
|
||||
|
||||
ProxyPython::~ProxyPython()
|
||||
{
|
||||
delete m_Runner;
|
||||
|
||||
if (!m_TempRunnerFile.isEmpty()) {
|
||||
::FreeLibrary(m_RunnerLib);
|
||||
QFile(m_TempRunnerFile).remove();
|
||||
}
|
||||
}
|
||||
|
||||
typedef IPythonRunner* (*CreatePythonRunner_func)(const QString &pythonPath);
|
||||
|
||||
|
||||
bool ProxyPython::init(IOrganizer *moInfo)
|
||||
{
|
||||
using CreatePythonRunner_func = IPythonRunner * (*)();
|
||||
|
||||
m_MOInfo = moInfo;
|
||||
|
||||
if (m_MOInfo && !m_MOInfo->isPluginEnabled(this)) {
|
||||
m_LoadFailure = FAIL_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_LoadFailure = FAIL_OTHER;
|
||||
if (QCoreApplication::applicationDirPath().contains(';')) {
|
||||
m_LoadFailure = FAIL_SEMICOLON;
|
||||
m_LoadFailure = FailureType::SEMICOLON;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString pythonPath;
|
||||
// load the pythonrunner library
|
||||
m_RunnerLib = ::LoadLibraryW(QDir::toNativeSeparators(
|
||||
IOrganizer::getPluginDataPath() + "/pythonRunner.dll").toStdWString().c_str());
|
||||
|
||||
if (m_MOInfo) {
|
||||
pythonPath = m_MOInfo->pluginSetting(name(), "python_dir").toString();
|
||||
if (!m_RunnerLib) {
|
||||
DWORD error = ::GetLastError();
|
||||
log::error("failed to load python runner ({}): {}", qUtf8Printable(windowsErrorString(error)));
|
||||
if (error == ERROR_MOD_NOT_FOUND) {
|
||||
m_LoadFailure = FailureType::DLL_NOT_FOUND;
|
||||
}
|
||||
else {
|
||||
m_LoadFailure = FailureType::INVALID_DLL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!pythonPath.isEmpty() && !QFile::exists(pythonPath + "/python.exe")) {
|
||||
m_LoadFailure = FAIL_WRONGPYTHONPATH;
|
||||
const CreatePythonRunner_func createPythonRunner = (CreatePythonRunner_func)::GetProcAddress(m_RunnerLib, "CreatePythonRunner");
|
||||
if (!createPythonRunner) {
|
||||
m_LoadFailure = FailureType::INVALID_DLL;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_MOInfo && m_MOInfo->persistent(name(), "tryInit", false).toBool()) {
|
||||
m_LoadFailure = FailureType::INITIALIZATION;
|
||||
if (QMessageBox::question(parentWidget(), tr("Python Initialization failed"),
|
||||
tr("On a previous start the Python Plugin failed to initialize.\n"
|
||||
"Do you want to try initializing python again (at the risk of another crash)?\n"
|
||||
"Suggestion: Select \"no\", and click the warning sign for further help. Afterwards you have to re-enable the python plugin."),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) {
|
||||
|
||||
// we force enabled here (note: this is a persistent settings since MO2 2.4 or something), plugin
|
||||
// usually should not handle enabled/disabled themselves but this is a base plugin so...
|
||||
m_MOInfo->setPersistent(name(), "enabled", false, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
m_RunnerLib = ::LoadLibraryW(QDir::toNativeSeparators(
|
||||
IOrganizer::getPluginDataPath() + "/pythonRunner.dll").toStdWString().c_str());
|
||||
|
||||
if (m_RunnerLib != nullptr) {
|
||||
CreatePythonRunner_func CreatePythonRunner = (CreatePythonRunner_func)::GetProcAddress(m_RunnerLib, "CreatePythonRunner");
|
||||
if (CreatePythonRunner == nullptr) {
|
||||
throw Exception("embedded dll is invalid: " + windowsErrorString(::GetLastError()));
|
||||
}
|
||||
|
||||
if (m_MOInfo && m_MOInfo->persistent(name(), "tryInit", false).toBool()) {
|
||||
if (pythonPath.isEmpty()) {
|
||||
m_LoadFailure = FAIL_PYTHONDETECTION;
|
||||
} else {
|
||||
m_LoadFailure = FAIL_WRONGPYTHONPATH;
|
||||
}
|
||||
if (QMessageBox::question(parentWidget(), tr("Python Initialization failed"),
|
||||
tr("On a previous start the Python Plugin failed to initialize.\n"
|
||||
"Either the value in Settings->Plugins->ProxyPython->plugin_dir is set incorrectly or it is empty and auto-detection doesn't work "
|
||||
"for whatever reason.\n"
|
||||
"Do you want to try initializing python again (at the risk of another crash)?\n"
|
||||
"Suggestion: Select \"no\", and click the warning sign for further help. Afterwards you have to re-enable the python plugin."),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) {
|
||||
m_MOInfo->setPluginSetting(name(), "enabled", false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_MOInfo) {
|
||||
m_MOInfo->setPersistent(name(), "tryInit", true);
|
||||
}
|
||||
|
||||
m_Runner = CreatePythonRunner(pythonPath);
|
||||
|
||||
if (m_MOInfo) {
|
||||
m_MOInfo->setPersistent(name(), "tryInit", false);
|
||||
}
|
||||
|
||||
if (m_Runner != nullptr) {
|
||||
m_LoadFailure = FAIL_NONE;
|
||||
} else {
|
||||
m_LoadFailure = FAIL_INITFAIL;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
DWORD error = ::GetLastError();
|
||||
qCritical("Failed to load python runner (%s): %s", qUtf8Printable(m_TempRunnerFile), qUtf8Printable(windowsErrorString(error)));
|
||||
if (error == ERROR_MOD_NOT_FOUND) {
|
||||
m_LoadFailure = FAIL_MISSINGDEPENDENCIES;
|
||||
}
|
||||
return true;
|
||||
if (m_MOInfo) {
|
||||
m_MOInfo->setPersistent(name(), "tryInit", true);
|
||||
}
|
||||
|
||||
m_Runner = std::unique_ptr<IPythonRunner>{ createPythonRunner() };
|
||||
|
||||
if (m_MOInfo) {
|
||||
m_MOInfo->setPersistent(name(), "tryInit", false);
|
||||
}
|
||||
|
||||
if (!m_Runner) {
|
||||
m_LoadFailure = FailureType::INITIALIZATION;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString ProxyPython::name() const
|
||||
@@ -216,15 +130,12 @@ QString ProxyPython::description() const
|
||||
|
||||
VersionInfo ProxyPython::version() const
|
||||
{
|
||||
return VersionInfo(2, 2, 0, VersionInfo::RELEASE_FINAL);
|
||||
return VersionInfo(2, 3, 0, VersionInfo::RELEASE_FINAL);
|
||||
}
|
||||
|
||||
QList<PluginSetting> ProxyPython::settings() const
|
||||
{
|
||||
QList<PluginSetting> result;
|
||||
result.push_back(PluginSetting("python_dir", "Path to your python installation. Leave empty for auto-detection", ""));
|
||||
result.push_back(PluginSetting("enabled", "Set to true to enable support for python plugins", true));
|
||||
return result;
|
||||
return {};
|
||||
}
|
||||
|
||||
QStringList ProxyPython::pluginList(const QDir& pluginPath) const
|
||||
@@ -269,103 +180,63 @@ void ProxyPython::unload(const QString& identifier)
|
||||
|
||||
std::vector<unsigned int> ProxyPython::activeProblems() const
|
||||
{
|
||||
std::vector<unsigned int> result;
|
||||
if (m_LoadFailure == FAIL_MISSINGDEPENDENCIES) {
|
||||
result.push_back(PROBLEM_PYTHONMISSING);
|
||||
} else if (m_LoadFailure == FAIL_WRONGPYTHONPATH) {
|
||||
result.push_back(PROBLEM_WRONGPYTHONPATH);
|
||||
} else if (m_LoadFailure == FAIL_PYTHONDETECTION) {
|
||||
result.push_back(PROBLEM_PYTHONDETECTION);
|
||||
} else if (m_LoadFailure == FAIL_INITFAIL) {
|
||||
result.push_back(PROBLEM_INITFAIL);
|
||||
} else if (m_LoadFailure == FAIL_SEMICOLON) {
|
||||
result.push_back(PROBLEM_SEMICOLON);
|
||||
} else if (m_Runner != nullptr) {
|
||||
if (!m_Runner->isPythonInstalled()) {
|
||||
// don't know how this could happen but wth
|
||||
result.push_back(PROBLEM_PYTHONMISSING);
|
||||
}
|
||||
if (!m_Runner->isPythonVersionSupported()) {
|
||||
result.push_back(PROBLEM_PYTHONWRONGVERSION);
|
||||
}
|
||||
auto failure = m_LoadFailure;
|
||||
|
||||
// don't know how this could happen but wth
|
||||
if (m_Runner && !m_Runner->isPythonInitialized()) {
|
||||
failure = FailureType::INITIALIZATION;
|
||||
}
|
||||
|
||||
return result;
|
||||
if (failure != FailureType::NONE) {
|
||||
return { static_cast<std::underlying_type_t<FailureType>>(failure) };
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QString ProxyPython::shortDescription(unsigned int key) const
|
||||
{
|
||||
switch (key) {
|
||||
case PROBLEM_PYTHONMISSING: {
|
||||
return tr("Python not installed or not found");
|
||||
} break;
|
||||
case PROBLEM_PYTHONWRONGVERSION: {
|
||||
return tr("Python version is incompatible");
|
||||
} break;
|
||||
case PROBLEM_WRONGPYTHONPATH: {
|
||||
return tr("Invalid python path");
|
||||
} break;
|
||||
case PROBLEM_INITFAIL: {
|
||||
return tr("Initializing Python failed");
|
||||
} break;
|
||||
case PROBLEM_PYTHONDETECTION: {
|
||||
return tr("Python auto-detection failed");
|
||||
} break;
|
||||
case PROBLEM_SEMICOLON: {
|
||||
switch (static_cast<FailureType>(key)) {
|
||||
case FailureType::SEMICOLON:
|
||||
return tr("ModOrganizer path contains a semicolon");
|
||||
} break;
|
||||
case FailureType::DLL_NOT_FOUND:
|
||||
return tr("Python DLL not found");
|
||||
case FailureType::INVALID_DLL:
|
||||
return tr("Invalid Python DLL");
|
||||
case FailureType::INITIALIZATION:
|
||||
return tr("Initializing Python failed");
|
||||
default:
|
||||
throw Exception(tr("invalid problem key %1").arg(key));
|
||||
return tr("invalid problem key %1").arg(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString ProxyPython::fullDescription(unsigned int key) const
|
||||
{
|
||||
switch (key) {
|
||||
case PROBLEM_PYTHONMISSING: {
|
||||
return tr("Some MO plugins require the python interpreter to be installed. "
|
||||
"These plugins will not even show up in settings->plugins.<br>"
|
||||
"If you want to use those plugins, please install the 32-bit version of Python 2.7.x from <a href=\"%1\">%1</a>.<br>"
|
||||
"This is only required to use some extended functionality in MO, you do not need Python to play the game.").arg(s_DownloadPythonURL);
|
||||
} break;
|
||||
case PROBLEM_PYTHONWRONGVERSION: {
|
||||
return tr("Your installed python version has a different version than 2.7. "
|
||||
"Some MO plugins may not work.<br>"
|
||||
"If you have multiple versions of python installed you may have to configure the path to 2.7 (32 bit) "
|
||||
"in the settings dialog.<br>"
|
||||
"This is only required to use some extended functionality in MO, you do not need Python to play the game.");
|
||||
} break;
|
||||
case PROBLEM_WRONGPYTHONPATH: {
|
||||
return tr("Please set python_dir in Settings->Plugins->ProxyPython to the path of your python 2.7 (32 bit) installation.");
|
||||
} break;
|
||||
case PROBLEM_PYTHONDETECTION: {
|
||||
return tr("The auto-detection of the python path failed. I don't know why this would happen but you can try to fix it "
|
||||
"by setting python_dir in Settings->Plugins->ProxyPython to the path of your python 2.7 (32 bit) installation.");
|
||||
} break;
|
||||
case PROBLEM_INITFAIL: {
|
||||
return tr("Sorry, I don't know any details. Most likely your python installation is not supported.");
|
||||
} break;
|
||||
case PROBLEM_SEMICOLON: {
|
||||
return tr("The path to Mod Organizer (%1) contains a semicolon. <br>"
|
||||
"While this is legal on NTFS drives there is a lot of software that doesn't handle it correctly.<br>"
|
||||
"Unfortunately MO depends on libraries that seem to fall into that group.<br>"
|
||||
"As a result the python plugin can't be loaded.<br>"
|
||||
"The only solution I can offer is to remove the semicolon / move MO to a path without a semicolon.").arg(QCoreApplication::applicationDirPath());
|
||||
} break;
|
||||
default:
|
||||
throw Exception(QString("invalid problem key %1").arg(key));
|
||||
switch (static_cast<FailureType>(key)) {
|
||||
case FailureType::SEMICOLON:
|
||||
return tr("The path to Mod Organizer (%1) contains a semicolon. <br>"
|
||||
"While this is legal on NTFS drives, many softwares do not handle it correctly.<br>"
|
||||
"Unfortunately MO depends on libraries that seem to fall into that group.<br>"
|
||||
"As a result the python plugin cannot be loaded, and the only solution we can"
|
||||
"offer is to remove the semicolon or move MO to a path without a semicolon.").arg(QCoreApplication::applicationDirPath());
|
||||
case FailureType::DLL_NOT_FOUND:
|
||||
return tr("The Python plugin DLL was not found, maybe your antivirus deleted it. Re-installing MO2 might fix the problem.");
|
||||
case FailureType::INVALID_DLL:
|
||||
return tr("The Python plugin DLL is invalid, maybe your antivirus is blocking it. "
|
||||
"Re-installing MO2 and adding exclusions for it to your AV might fix the problem.");
|
||||
case FailureType::INITIALIZATION:
|
||||
return tr("The initialization of the Python plugin DLL failed, unfortunately without any details.");
|
||||
default:
|
||||
return tr("invalid problem key %1").arg(key);
|
||||
}
|
||||
}
|
||||
|
||||
bool ProxyPython::hasGuidedFix(unsigned int key) const
|
||||
{
|
||||
return (key == PROBLEM_PYTHONMISSING) || (key == PROBLEM_PYTHONWRONGVERSION);
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProxyPython::startGuidedFix(unsigned int key) const
|
||||
{
|
||||
if ((key == PROBLEM_PYTHONMISSING) || (key == PROBLEM_PYTHONWRONGVERSION)) {
|
||||
::ShellExecuteA(nullptr, "open", s_DownloadPythonURL, nullptr, nullptr, SW_SHOWNORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
+29
-43
@@ -20,11 +20,14 @@ along with python proxy plugin. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef PROXYPYTHON_H
|
||||
#define PROXYPYTHON_H
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <ipluginproxy.h>
|
||||
#include <iplugindiagnose.h>
|
||||
#include <map>
|
||||
#include <Windows.h>
|
||||
|
||||
#include <pythonrunner.h>
|
||||
|
||||
|
||||
@@ -38,59 +41,42 @@ class ProxyPython : public QObject, public MOBase::IPluginProxy, public MOBase::
|
||||
|
||||
public:
|
||||
ProxyPython();
|
||||
~ProxyPython();
|
||||
|
||||
virtual bool init(MOBase::IOrganizer *moInfo);
|
||||
virtual QString name() const;
|
||||
virtual QString localizedName() const;
|
||||
virtual QString author() const;
|
||||
virtual QString description() const;
|
||||
virtual MOBase::VersionInfo version() const;
|
||||
virtual QList<MOBase::PluginSetting> settings() const;
|
||||
virtual QString name() const override;
|
||||
virtual QString localizedName() const override;
|
||||
virtual QString author() const override;
|
||||
virtual QString description() const override;
|
||||
virtual MOBase::VersionInfo version() const override;
|
||||
virtual QList<MOBase::PluginSetting> settings() const override;
|
||||
|
||||
QStringList pluginList(const QDir& pluginPath) const;
|
||||
QList<QObject*> load(const QString& identifier);
|
||||
void unload(const QString& identifier);
|
||||
|
||||
/**
|
||||
* @return the parent widget for newly created dialogs
|
||||
* @note needs to be public so it can be exposed to plugins
|
||||
*/
|
||||
virtual QWidget *getParentWidget() { return parentWidget(); }
|
||||
QStringList pluginList(const QDir& pluginPath) const override;
|
||||
QList<QObject*> load(const QString& identifier) override;
|
||||
void unload(const QString& identifier) override;
|
||||
|
||||
public: // IPluginDiagnose
|
||||
|
||||
virtual std::vector<unsigned int> activeProblems() const;
|
||||
virtual QString shortDescription(unsigned int key) const;
|
||||
virtual QString fullDescription(unsigned int key) const;
|
||||
virtual bool hasGuidedFix(unsigned int key) const;
|
||||
virtual void startGuidedFix(unsigned int key) const;
|
||||
virtual std::vector<unsigned int> activeProblems() const override;
|
||||
virtual QString shortDescription(unsigned int key) const override;
|
||||
virtual QString fullDescription(unsigned int key) const override;
|
||||
virtual bool hasGuidedFix(unsigned int key) const override;
|
||||
virtual void startGuidedFix(unsigned int key) const override;
|
||||
|
||||
private:
|
||||
|
||||
static const unsigned int PROBLEM_PYTHONMISSING = 1;
|
||||
static const unsigned int PROBLEM_PYTHONWRONGVERSION = 2;
|
||||
static const unsigned int PROBLEM_WRONGPYTHONPATH = 3;
|
||||
static const unsigned int PROBLEM_INITFAIL = 4;
|
||||
static const unsigned int PROBLEM_PYTHONDETECTION = 5;
|
||||
static const unsigned int PROBLEM_SEMICOLON = 6;
|
||||
static const char *s_DownloadPythonURL;
|
||||
|
||||
MOBase::IOrganizer *m_MOInfo;
|
||||
QString m_TempRunnerFile;
|
||||
HMODULE m_RunnerLib;
|
||||
IPythonRunner *m_Runner;
|
||||
std::unique_ptr<IPythonRunner> m_Runner;
|
||||
|
||||
enum {
|
||||
FAIL_NONE,
|
||||
FAIL_SEMICOLON,
|
||||
FAIL_NOTINIT,
|
||||
FAIL_MISSINGDEPENDENCIES,
|
||||
FAIL_INITFAIL,
|
||||
FAIL_WRONGPYTHONPATH,
|
||||
FAIL_PYTHONDETECTION,
|
||||
FAIL_OTHER
|
||||
} m_LoadFailure;
|
||||
enum class FailureType : unsigned int {
|
||||
NONE = 0,
|
||||
SEMICOLON = 1,
|
||||
DLL_NOT_FOUND = 2,
|
||||
INVALID_DLL = 3,
|
||||
INITIALIZATION = 4
|
||||
};
|
||||
|
||||
FailureType m_LoadFailure;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1160,12 +1160,12 @@ public:
|
||||
PythonRunner();
|
||||
~PythonRunner();
|
||||
|
||||
bool initPython(const QString& pythonDir);
|
||||
bool initPython();
|
||||
|
||||
QList<QObject*> load(const QString& identifier);
|
||||
void unload(const QString& identifier);
|
||||
|
||||
bool isPythonInstalled() const;
|
||||
bool isPythonInitialized() const;
|
||||
bool isPythonVersionSupported() const;
|
||||
|
||||
private:
|
||||
@@ -1197,14 +1197,13 @@ private:
|
||||
wchar_t* m_PythonHome;
|
||||
};
|
||||
|
||||
IPythonRunner* CreatePythonRunner(const QString& pythonDir)
|
||||
IPythonRunner* CreatePythonRunner()
|
||||
{
|
||||
PythonRunner* result = new PythonRunner;
|
||||
if (result->initPython(pythonDir)) {
|
||||
return result;
|
||||
std::unique_ptr<PythonRunner> result = std::make_unique<PythonRunner>();
|
||||
if (result->initPython()) {
|
||||
return result.release();
|
||||
}
|
||||
else {
|
||||
delete result;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1302,19 +1301,11 @@ BOOST_PYTHON_MODULE(moprivate)
|
||||
}, bpy::arg("callback") = bpy::object{});
|
||||
}
|
||||
|
||||
bool PythonRunner::initPython(const QString &pythonPath)
|
||||
bool PythonRunner::initPython()
|
||||
{
|
||||
if (Py_IsInitialized())
|
||||
return true;
|
||||
try {
|
||||
if (!pythonPath.isEmpty() && !QFile::exists(pythonPath + "/python.exe")) {
|
||||
return false;
|
||||
}
|
||||
pythonPath.toWCharArray(m_PythonHome);
|
||||
if (!pythonPath.isEmpty()) {
|
||||
Py_SetPythonHome(m_PythonHome);
|
||||
}
|
||||
|
||||
wchar_t argBuffer[MAX_PATH];
|
||||
const size_t cSize = strlen(argv0) + 1;
|
||||
mbstowcs(argBuffer, argv0, MAX_PATH);
|
||||
@@ -1564,15 +1555,7 @@ void PythonRunner::unload(const QString& identifier)
|
||||
}
|
||||
}
|
||||
|
||||
bool PythonRunner::isPythonInstalled() const
|
||||
bool PythonRunner::isPythonInitialized() const
|
||||
{
|
||||
return Py_IsInitialized() != 0;
|
||||
}
|
||||
|
||||
|
||||
bool PythonRunner::isPythonVersionSupported() const
|
||||
{
|
||||
const char *version = Py_GetVersion();
|
||||
return strstr(version, "3.8") == version;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@ public:
|
||||
virtual QList<QObject*> load(const QString& identifier) = 0;
|
||||
virtual void unload(const QString& identifier) = 0;
|
||||
|
||||
virtual bool isPythonInstalled() const = 0;
|
||||
virtual bool isPythonVersionSupported() const = 0;
|
||||
virtual bool isPythonInitialized() const = 0;
|
||||
|
||||
virtual ~IPythonRunner() { }
|
||||
};
|
||||
@@ -27,7 +26,7 @@ public:
|
||||
#define PYDLLEXPORT Q_DECL_IMPORT
|
||||
#endif // PYTHONRUNNER_LIBRARY
|
||||
|
||||
extern "C" PYDLLEXPORT IPythonRunner *CreatePythonRunner(const QString &pythonDir);
|
||||
extern "C" PYDLLEXPORT IPythonRunner *CreatePythonRunner();
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user