Я пытаюсь создать программу на C ++ / Qt5, которая использует встроенный интерпретатор Python3 для сценариев и настройки.
Это мой подход:
Я создаю экземпляр QApplication в C ++, создаю экземпляр QMainwindow и добавляю QVBoxLayout и QPushbutton.
Затем я инициализирую интерпретатор Python, импортирую модуль python, содержащий некоторый базовый код PyQt для добавления второго QPushButton в QVBoxLayout, и выполняю этот код.
Затем, вернувшись в C ++, я вызываю ‘show ()’ для экземпляра QMainWindow и выполняю QApplication.
После возврата QApplication :: exec ()enter code here
s, я пытаюсь очистить ссылки на PyObjects и пытаюсь завершить интерпретатор Python.
Зов Py_Finalize()
вызывает ошибку сегментации.
Вот код:
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QPushButton>
#include <QMainWindow>
#pragma push_macro("slots")
#undef slots
#include "Python.h"#pragma pop_macro("slots")
int main(int argc, char *argv[])
{
PyObject *pName, *pModule, *pDict, *pFunc;// Initialize QApplication and setup basic widgets.
QApplication app (argc, argv);
QMainWindow mainWindow (nullptr);
QPushButton button ("test", &mainWindow);
QWidget * widget = new QWidget(&mainWindow);
mainWindow.setCentralWidget(widget);
auto l = new QVBoxLayout ();
widget->setLayout(l);
l->addWidget(&button);
// Initialize the Python Interpreter
Py_Initialize();// Build the name object
pName = PyUnicode_FromString("runPyQt");
// Load the module object
pModule = PyImport_Import(pName);
if (!pModule){
Py_Finalize();
return 1;
}
pDict = PyModule_GetDict(pModule);
pFunc = PyDict_GetItemString(pDict, "main");
if (PyCallable_Check(pFunc))
{
PyObject_CallObject(pFunc, nullptr);
} else
{
PyErr_Print();
}
mainWindow.show();
int r = 0;
r = QApplication::exec();
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
Py_Finalize();
return r;
}
И модуль Python:
import sys
if sys.platform.startswith( 'linux' ) :
from OpenGL import GL
from PyQt5.QtWidgets import QApplication, QPushButton, QMainWindowdef main():
app = QApplication.instance()
widgets = app.topLevelWidgets()
for widget in widgets:
if type(widget) is QMainWindow:
break
widget = widget.centralWidget()
widget.layout().addWidget(QPushButton('Hello from PyQt'))
Я предположил, что это как-то связано с отсутствием GIL при финализации интерпретатора. Я пробовал звонить PyEval_AcquireLock()
прямо перед финализацией, что приводит к зависанию программы в этой точке.
Возможно, PyQt где-то получает блокировку и не снимает ее до завершения, но это только предположение.
До вызова Py_Finalize()
программа работает именно так, как я ожидаю. Даже использование PyQt для добавления некоторых нетривиальных виджетов работает нормально.
Мой вопрос: как мне правильно завершить интерпретатор Python в этой ситуации?
Задача ещё не решена.
Других решений пока нет …