PyQt script under C++ Qt doesn't work under Windows.
-
wrote on 5 Mar 2020, 19:53 last edited by
I'm trying to run a Python (PyQt) script under a Qt C++ applciation. This script works fine from console (linux) and cmd (windows 10).
This is the script:
plugin_loader.py
#!/usr/bin/python # -*- coding: utf-8 -*- import imp import os import sys import operator from PyQt5 import QtCore, QtGui, QtWidgets, QtSql from DialogoImprimir import DialogoImprimir if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) myapp = DialogoImprimir() myapp.show() sys.exit(app.exec_()) def iniciar(*datos): app = QtWidgets.QApplication.instance() print (app) if app is None: app = QtWidgets.QApplication([]) myapp = DialogoImprimir() myapp.show() return myapp.exec_()
#!/usr/bin/python # -*- coding: utf-8 -*- MainModule = "__init__" import sys import imp import os from PyQt5 import QtCore, QtGui, QtWidgets class DialogoImprimir(QtWidgets.QDialog): def __init__(self): QtWidgets.QDialog.__init__(self) self.GeneraUI() def GeneraUI(self): self.setObjectName("Dialog") self.resize(200, 293) self.buttonBox = QtWidgets.QDialogButtonBox(self) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) self.buttonBox.setObjectName("buttonBox") self.retranslateUi() #acciones self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) QtCore.QMetaObject.connectSlotsByName(self) def retranslateUi(self): _translate = QtCore.QCoreApplication.translate
main.cpp
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindows.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
mainwindows.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include "./pyrun.h" #include <QDebug> #include <QDir> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QString pathPython = "/.pruebapython"; QString pRuta = QDir::homePath()+pathPython; QString pModulo = "plugin_loader"; QString pFuncion = "iniciar"; QStringList pArgumentos; pArgumentos<<"1"<<"2"<<"3"<<"4"; int res = ::PyRun::loadModule(QDir::home().absoluteFilePath(pRuta),pModulo, pFuncion, pArgumentos); qDebug()<<"Resultado: "<<res; } MainWindow::~MainWindow() { delete ui; }
pyrun.h
#ifndef PYRUN_H #define PYRUN_H //se crea un entorno para cargar modulos en python #include <QString> #include <QStringList> namespace PyRun { enum State { PythonUninitialized, PythonInitialized, AppModuleLoaded }; enum Resultado { CannotLoadModule, CannotConvertArgument, CallFailed, CannotFindFunction, FailedToLoad, Success }; int loadModule(const QString &modulePath, const QString &moduleName, const QString &functionName, const QStringList &args); State init(); } #endif // PYRUN_H
pyrun.cpp
#include "pyrun.h" #include <Python.h> #include <QByteArray> #include <QCoreApplication> #include <QDebug> namespace PyRun { static State state = PythonUninitialized; static void cleanup() { if (state > PythonUninitialized) { Py_Finalize(); state = PythonUninitialized; } } int loadModule(const QString &modulePath, const QString &moduleName, const QString &functionName, const QStringList& args) { qDebug()<<"modulepath"<<modulePath; qputenv("PYTHONPATH", modulePath.toLocal8Bit()); if (init() != AppModuleLoaded) //return false; return CannotLoadModule; PyObject *pName, *pModule, *pFunc; PyObject *pArgs, *pValue; pName = PyUnicode_DecodeFSDefault(moduleName.toLocal8Bit().constData()); /* Error checking of pName left out */ pModule = PyImport_Import(pName); Py_DECREF(pName); if (pModule) { pFunc = PyObject_GetAttrString(pModule, functionName.toLocal8Bit().constData()); /* pFunc is a new reference */ if (pFunc && PyCallable_Check(pFunc)) { /* pValue reference stolen here: */ pArgs = PyTuple_New(args.size()); for (int i = 0;i<args.size();i++) { PyObject* arg_valor = Py_BuildValue("s",args.at(i).toLocal8Bit().constData()); if (!arg_valor) { Py_DECREF(pArgs); Py_DECREF(pModule); qWarning("Cannot convert argument\n"); //return false; return CannotConvertArgument; } PyTuple_SetItem(pArgs, i, arg_valor);//meto los datos de conexion } pValue = PyObject_CallObject(pFunc, pArgs); Py_DECREF(pArgs); if (pValue){ qWarning("Result of call: %ld\n", PyLong_AsLong(pValue)); Py_DECREF(pValue); } else { Py_DECREF(pFunc); Py_DECREF(pModule); PyErr_Print(); qWarning("Call failed\n"); //return false; return CallFailed; } } else { if (PyErr_Occurred()) PyErr_Print(); qWarning("Cannot find function \"%s\"\n", functionName.toLocal8Bit().constData()); } Py_XDECREF(pFunc); Py_DECREF(pModule); } else { PyErr_Print(); qWarning("Failed to load \"%s\"\n", moduleName.toLocal8Bit().constData()); //return false; return FailedToLoad; } //return true; return Success; } State init() { if (state > PythonUninitialized) return state; QByteArray virtualEnvPath = qgetenv("VIRTUAL_ENV"); if (!virtualEnvPath.isEmpty()) qputenv("PYTHONHOME", virtualEnvPath); Py_Initialize(); qAddPostRoutine(cleanup); state = PythonInitialized; const bool pyErrorOccurred = PyErr_Occurred() != nullptr; if (!pyErrorOccurred) { state = AppModuleLoaded; } else { if (pyErrorOccurred) PyErr_Print(); qWarning("Failed to initialize the module."); } return state; } }
More things....the *.pro file has these lines (in my case):
unix { INCLUDEPATH += /usr/include/python3.6m LIBS += -L /usr/local/lib/python3.6 -lpython3.6m DEPENDPATH += /usr/include/python3.6m } win32 { INCLUDEPATH += C:\Python\Python37\include LIBS += -L C:\Python\Python37\libs -lpython37 DEPENDPATH += C:\Python\Python37\include }
Actually, it is my clumsy version of the answer of this
Well, running the script under linux there aren't any error, but under windows I have a white windows, without buttons or information on. Then the applicatios fails, and I must to force for close it.
I have this message:QApplication::regClass: Registering window class 'Qt5ClipboardView' failed. (Esta clase ya existe.)
And if I move the mouse over the white window I have these messages:
windowsProc: No Qt Window found for event 0x20 (WM_SETCURSOR), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x200 (WM_MOUSEMOVE), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x84 (WM_NCHITTEST), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x20 (WM_SETCURSOR), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x200 (WM_MOUSEMOVE), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x84 (WM_NCHITTEST), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x20 (WM_SETCURSOR), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x200 (WM_MOUSEMOVE), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x84 (WM_NCHITTEST), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x20 (WM_SETCURSOR), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x200 (WM_MOUSEMOVE), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x6 (WM_ACTIVATE), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x1c (WM_ACTIVATEAPP), hwnd=0x0xf0470.
windowsProc: No Qt Window found for event 0x8 (WM_KILLFOCUS), hwnd=0x0xf0470.Sorry about my poor english.
Thank you!
1/1