功能:
qt中用多线程的方式调用python脚本,完成C++和python之间的数据交互。为了满足多任务并发的要求,将调用python的逻辑部分封装到QThread的子类PyApiThread中。
主要实现:
包括PyApiThread的实现以及在主线程中如何使用
PyApiThread的的实现,分.h和.cpp两个文件
#ifndef PYAPITHREAD_H
#define PYAPITHREAD_H#include "Python.h"
#include <QMap>
#include <QQueue>
#include <QThread>
#include <QVariant>class QMutex;
class Widget;
class QEventLoop;
class PyApiThread : public QThread
{Q_OBJECT
public: explicit PyApiThread(Widget* parent = nullptr);~PyApiThread();bool isRunning()const;void setSleepTime(uint ms); Q_INVOKABLE void stopRuning(); Q_INVOKABLE void stopPyApi(const QString& pyfile);void addPyApi(const QString& pyfile, const QString& function,const QStringList& paramters, const QVariant& attachInfo=""); signals:void stopThreadWork();void startPyApiTask(const QString& api);void finishPyApiTask(const QString& api, bool cancel);void pyCommandResult(const QVariant& result);protected:void run();private:QVariant getPyCmd();QVariant getPyCmdResult();void addPyApiResult(const QVariant& result);bool cancelPyApi();void sleepThread(uint ms); void initPythonEnviroement();QVariant parsePyObj(PyObject* obj);QVariant parsePyList(PyObject* obj);QVariant parsePyTuple(PyObject* obj);QVariant parsePyDictionary(PyObject* obj);QVariant parsePySimpleObj(PyObject* obj);const char* printPyApiError(const QString& prefix);QVariant executePyScript(const QString& pyfile, const QString& function,const QStringList& paramters, const QVariant& attachInfo);bool needExecuteExterProcess(const QString &pyfile, const QStringList ¶mters, QVariantMap& result);int executeExterProcess(const QString &pyfile, const QStringList ¶mters);private:uint mSleepTime = 80;bool mRunning = false;//bool mPlatformInit = true;QQueue<QVariant> mApiQueue; //后面改成无锁队列 QQueue<QString> mSystemQueue; //后面改成无锁队列QQueue<QVariant> mApiQueueResult; //后面改成无锁队列QMutex* mMutex = nullptr; QMutex* mSysMutex = nullptr;QEventLoop* mEventLoop = nullptr;Widget* mParent{nullptr};//QMap<QString, QVariant(PyApiThread::*)(const QVariantMap&)> mFuncs;
};#endif // PYAPITHREAD_H
#include "pyapithread.h"
//#include "pyinterface.h"
#include "rlog.h"
#include "widget.h"#include <QDebug>
#include <QMutex>
#include <QTimer>
#include <QWidget>
#include <QDateTime>
#include <QEventLoop>
#include <QtConcurrent>
#include <QCoreApplication>class PythonThreadLocker
{PyGILState_STATE state;
public:PythonThreadLocker() : state(PyGILState_Ensure()){}~PythonThreadLocker() {PyGILState_Release(state);}
};PyApiThread::PyApiThread(Widget *parent):mParent(parent)
{
}PyApiThread::~PyApiThread()
{if(mMutex){delete mMutex;mMutex = nullptr;}if(mSysMutex){delete mSysMutex;mSysMutex = nullptr;}if(mEventLoop){mEventLoop->quit();delete mEventLoop;mEventLoop = nullptr;}}void PyApiThread::stopRuning()
{ mRunning = false;mEventLoop->quit();emit stopThreadWork();qDebug()<<"stopRuning