которая решает проблему:

я есть приложение C ++ / Qt, в которое я хочу встроить интерпретатор Python. Я хочу вызвать Python из QThread, но я получаю тупик в строке, где я вызываю PyGILState_Ensure (), чтобы попытаться получить глобальную блокировку интерпретатора (GIL).

Я приведу минимальный и простой пример ниже, который следует рекомендациям, даннымВот:

//main.cpp:
#include <QCoreApplication>
#include <QThread>
#include "Worker.h"

void startThread()
{
    QThread* thread = new QThread;
    Worker* worker = new Worker();
    worker->moveToThread(thread);
    QObject::connect(thread, SIGNAL(started()), worker, SLOT(process()));
    QObject::connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Py_Initialize();
    startThread();
    Py_FinalizeEx();
    return a.exec();
}


//Worker.h:
#ifndef WORKER_H
#define WORKER_H

#include <QObject>
#include "Python.h"

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr) : QObject(parent) {}

Q_SIGNALS:
    void finished();

public Q_SLOTS:
    void process()
    {
        qDebug("Calling Python");
        PyGILState_STATE gstate = PyGILState_Ensure();
        PyRun_SimpleString("print(\"hello\")");
        PyGILState_Release(gstate);
        qDebug("Done calling Python");
        Q_EMIT finished();
    }
};

#endif // WORKER_H

Некоторые дополнительные комментарии:

Примечание. Файл .pro содержит строкуCONFIG += no_keywords, чтобы избежать конфликтов имен с заголовком Python.Следует отметить, что хотя поток останавливает выполнение при вызове PyGILState_Ensure (), основной поток продолжает не блокироваться. Если я изменюreturn a.exec(); вreturn 0;, программа выйдет. (Так что, возможно, тупик - неправильный термин.)Обратите внимание, что я не заинтересован в создании потоков внутри Python. Я просто хочу прямо вызвать данный скрипт Python из QThread.Я читал другиеаналогичный вопросов, но чувствовал, что рассматриваемые там случаи немного отличаются, и я не смог решить мою проблему из ответов, данных там. Также меня смущают рекомендации звонитьPyEval_InitThreads()что если я понимаюДокументация по API Python / C правильно, не нужно

Ответы на вопрос(1)

Ваш ответ на вопрос