#python #c #qt #pyqt #pyqt5
#python #c #qt #pyqt #pyqt5
Вопрос:
Я пытаюсь расширить свое приложение Qt с помощью плагинов python scripts. Он отлично работает, если я вызываю какой-либо скрипт, не pyqt. Он также отлично работает, если я вызываю любой скрипт pyqt из функции c , но я нахожусь за пределами приложения Qt Widget. Что-то вроде этого:
#include "/usr/include/python3.5m/Python.h"
int CargaPlugins(const char* ruta, const char* nombremodulo, const char* nombrefuncion);
int main(int argc, char** argv)
{
std::string path = "PYTHONPATH=";
path.append(argv[1]);
putenv ((char*)path.c_str());
Py_Initialize();
CargaPlugins(argv[1],"plugin_loader","iniciar");
Py_Finalize();
return 0;
}
int CargaPlugins(const char* ruta, const char* nombremodulo, const char* nombrefuncion)
{
PyObject *pName, *pModule, *pDict, *pFunc;
PyObject *pArgs, *pValue;
pName = PyUnicode_DecodeFSDefault(nombremodulo);
/* Error checking of pName left out */
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (pModule != NULL)
{
pFunc = PyObject_GetAttrString(pModule, nombrefuncion);
/* pFunc is a new reference */
if (pFunc amp;amp; PyCallable_Check(pFunc))
{
pArgs = PyTuple_New(1);
pValue = PyUnicode_FromString(ruta);
if (!pValue)
{
Py_DECREF(pArgs);
Py_DECREF(pModule);
fprintf(stderr, "Cannot convert argumentn");
return 1;
}
/* pValue reference stolen here: */
PyTuple_SetItem(pArgs, 0, pValue);
pValue = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
if (pValue != NULL)
{
printf("Result of call: %ldn", PyLong_AsLong(pValue));
Py_DECREF(pValue);
}
else
{
Py_DECREF(pFunc);
Py_DECREF(pModule);
PyErr_Print();
fprintf(stderr,"Call failedn");
return 1;
}
}
else
{
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function "%s"n", nombrefuncion);
}
Py_XDECREF(pFunc);
Py_DECREF(pModule);
}
else
{
PyErr_Print();
fprintf(stderr, "Failed to load "%s"n", nombremodulo);
return 1;
}
}
И модуль pyqt5:
plugin_loader.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import imp
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from DialogoImprimir import DialogoImprimir
def iniciar(ruta):
import sys
if not hasattr(sys,'argv'):
sys.argv = []
app = QtWidgets.QApplication(sys.argv)
myapp = DialogoImprimir(getPlugins(ruta))
myapp.show()
sys.exit(app.exec_())
DialogoImprimir.py
class DialogoImprimir(QtWidgets.QDialog):
def __init__(self, datos):
QtWidgets.QDialog.__init__(self)
self.datos = datos
self.GeneraUI(datos)
-------------------
Ну, моя проблема в том, что если я вставляю C int CargaPlugins(const char* ruta, const char* nombremodulo, const char* nombrefuncion)
в свое приложение Qt Widgwets как функцию, я получаю эту ошибку при вызове:
QCoreApplication::exec: цикл событий уже запущен
Я думаю, что решением было бы передать указатель текущего QApplication скрипту python, или, если есть какой-либо способ сделать это, получить текущее QApplication при запуске скрипта python и использовать его, но я не знаю, как это можно сделать.
Редактировать:
Фрагмент кода при вызове функции внутри Qt:
mainwindow.cpp
void MainWindow::ActionImprimir()
{
Imprimir impresor("/home/user/pathofpythonmodules/","plugin_loader","iniciar");
imprimir.cpp
Imprimir::Imprimir(const char* ruta, const char* nombremodulo, const char* nombrefuncion)
{
std::string path = "PYTHONPATH=";
path.append(ruta);
putenv ((char*)path.c_str());
Py_Initialize();
pFuncion = CargarPlugins(ruta,nombremodulo,nombrefuncion);
if (pFuncion)
{
//more things
}
}
(и CargarPlugins() — это та же функция, что и раньше)
Комментарии:
1. Вы могли бы показать, как вы вызываете эту функцию в своем приложении Qt
2. Спасибо @eyllanesc, я отредактировал вопрос
Ответ №1:
Поскольку у вас есть QApplication, нет необходимости создавать другое, поэтому решение:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import importlib
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from DialogoImprimir import DialogoImprimir
def iniciar(ruta):
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication([])
myapp = DialogoImprimir(getPlugins(ruta))
return myapp.exec_()
Полный пример вы найдете здесь
Комментарии:
1. Большое спасибо, @eyllanesc. Ваш полный пример, если это больше, чем ответ!