1、背景
简单说一下需求,Qt开发的上位机界面程序,需要调用Python编写的算法跑一个结果返回到界面上显示。
2、度娘出一篇博客,按照步骤进行环境搭建和简单的代码测试
环境搭建请参照如下博客地址:
博客:① https://blog.csdn.net/cholenmine/article/details/82854301
② https://blog.csdn.net/yinyuchen1/article/details/77775851
主要代码如下:
#include "Python.h"
voidMainWindow::test()
{//进行初始化
Py_Initialize();//如果初始化失败,返回
if(!Py_IsInitialized())
{
qDebug()<
}//加载模块,模块名称为myModule,就是myModule.py文件
PyObject *pModule = PyImport_ImportModule("myModule");//如果加载失败,则返回
if(!pModule)
{
qDebug()<
}//加载函数greatFunc
PyObject * pFuncHello = PyObject_GetAttrString(pModule, "greatFunc");//如果失败则返回
if(!pFuncHello)
{
qDebug()<
}
}
3、根据目前的具体需求,我需要在开启一个线程来调用Python脚本,于是新建了一个线程类,调用方法还是用的上面的示例代码。
.h文件
#ifndef CALCSCORETHREAD_H#define CALCSCORETHREAD_H#include#include#include
class CalcScoreThread : publicQThread
{
Q_OBJECTpublic:
CalcScoreThread(QObject*parent =nullptr);//html转化为PDF
QString saveHtmlToPDF(QString str);protected:voidrun();private:
QString m_ScoreType;
QString m_LabelPath;
};#endif //CALCSCORETHREAD_H
cpp文件
#include "CalcScoreThread.h"#include"LoggerInfo.h"#include#include#include#includeCalcScoreThread::CalcScoreThread(QObject*parent) : QThread(parent)
{
}void CalcScoreThread::SetScoreType(const QString &type)
{
m_ScoreType=type;
}voidCalcScoreThread::run()
{
Py_Initialize();//测试集路径
QString setsPath = QCoreApplication::applicationDirPath()+"/datasets/Divide_Labels";
QString name="main_SCORE";
LoggerInfo::GetInstance()->WriteLog("Start Import Module!");
PyObject* pModule = PyImport_ImportModule("main_SCORE");if (!pModule)
{
qDebug()<< "Cant open python file!";return;
}
LoggerInfo::GetInstance()->WriteLog("Import Module Succ!");//获取模块中的函数
PyObject* pFunc = PyObject_GetAttrString(pModule,"main");if(!pFunc)
{
qDebug()<< "Get function failed!";return;
}
QString strEnv= "5,2,2,3";
PyObject* pArgs = PyTuple_New(4);
PyTuple_SetItem(pArgs,0, Py_BuildValue("s",m_ScoreType.toStdString().c_str()));
PyTuple_SetItem(pArgs,1, Py_BuildValue("s",m_LabelPath.toStdString().c_str()));
PyTuple_SetItem(pArgs,2, Py_BuildValue("s",setsPath.toStdString().c_str()));
PyTuple_SetItem(pArgs,3, Py_BuildValue("s",strEnv.toStdString().c_str()));
PyObject* pReturn =PyObject_CallObject(pFunc, pArgs);if(pReturn)
{
qDebug()<< "succ ------";
}
Py_Finalize();if(!strResult.isEmpty())
{
emit SignalScoreResult(strResult);
}
}
现在问题来了:
① 第一次调用python脚本,能够正常调用并且得到结果。
② 不关闭主界面,接着进行第二次调用,软件直接崩溃,崩溃的行数是PyImport_ImportModule()函数,如下图所示:
最开始分析的原因:① 出现了空指针
② 第二次调用时,第一次的资源没有释放,占用python脚本,导致PyImport_ImportModule()函数不能将模块导入
4、最后差资料发现,因为我这里使用的是线程,C++多线调用python时必须要控制GIL
参照如下博客的方法才得以解决这个问题,对于小白初次线程中调用Python,鬼知道要控制什么GIL,虽然问题解决了,到现在都没去看GIL是个什么鬼
https://blog.csdn.net/qq_42938320/article/details/101770269