QT下调用py脚本的两种方法

如何实现在c++QT中调用py脚本呢?方法如下:

方法一:通过官方python.h进行调用

该方法参考了Ubuntu18.04下 Qt调用conda下的python_猫生鱼的博客-CSDN博客

感谢大佬的分享~~

1.在.pro文件中加入

##加入python库(根据实际位置调整路径)

LIBS += -L/usr/local/python3.7/lib -lpython3.7m -lcrypt -lpthread -ldl  -lutil -lm -lpython3

DEPENDPATH += /usr/local/python3.7/include/python3.7m

INCLUDEPATH += /usr/local/python3.7/include/python3.7m  -Wno-unused-result -Wsign-compare  -DNDEBUG -g -fwrapv -O3 -Wall

INCLUDEPATH += /usr/local/python3.7/lib/python3.7/site-packages/numpy/core/include

2.在需要调用py脚本的文件中加入

#undef slots

#include <Python.h>

#define slots Q_SLOTS

tip:为什么添加#undef slots #define slots Q_SLOTS?原因是python中的slots与qt中的slots 定义冲突

3. 在需要调用py脚本的.cpp文件中加入以下代码(可以在函数中加入)

   //以下为使用python.h调用py的代码

    Py_Initialize();// 解释器初始化

    if(!Py_IsInitialized()){

        PyErr_Print();

        qDebug() << "Can't Initialize python!\n" ;

        return ;

    }

    PyRun_SimpleString("import sys");//令python能找到已经安装的库,不加此句会出现无法import的问题

    PyRun_SimpleString("sys.argv = ['python.py']");

    PyRun_SimpleString("sys.path.append('./')");//把工作目录改为py文件所在目录,这里为当前目录

//导入.py文件模块,这里的project为文件名

PyObject* pModule = PyImport_ImportModule("project");

if(!pModule){

    PyErr_Print();

    qDebug() << "Can't open python file!\n" ;

    return;

}

//导入模块中的方法字典

PyObject* pDict = PyModule_GetDict(pModule);

if(!pDict){

    PyErr_Print();

    qDebug() << "Get Dict failed!\n" ;

   return;

}

//导入已导入模块中的方法或类,这里的main为方法(函数)名

PyObject* pFuc = PyDict_GetItemString(pDict, "main");

if(!pFuc){

    PyErr_Print();

    qDebug() << "Get function failed!\n" ;

    return;

}

//启用导入的方法或类

PyObject_CallFunction(pFuc,NULL);

//内存释放

Py_CLEAR(pModule);

Py_CLEAR(pDict);

Py_CLEAR(pFuc);

//释放Python解释器所占用的资源

Py_Finalize();

知识点补充:Python嵌入C/C++释放资源

Python使用引用计数机制对内存进行管理,实现自动垃圾回收。在C/C++中使用Python对象时,应正确地处理引用计数,否则容易导致内存泄漏。在Python/C API中提供了Py_CLEAR()、Py_DECREF()等宏来对引用计数进行操作。

当使用Python/C API中的函数创建列表、元组、字典等后,就在内存中生成了这些对象的引用计数。在对其完成操作后应该使用Py_CLEAR()、Py_DECREF()等宏来销毁这些对象。其原型分别如下所示。

void Py_CLEAR( PyObject *o)

void Py_DECREF( PyObject *o)

其参数含义如下。

*o:要进行操作的对象。

对于Py_CLEAR()其参数可以为NULL指针,此时,Py_CLEAR()不进行任何操作。而对于Py_DECREF()其参数不能为NULL指针,否则将导致错误。

方法二:通过多线程调用

#include "mainwindow.h"

#include "ui_mainwindow.h"

#include <QProcess>

#include <QtDebug>

MainWindow::MainWindow(QWidget *parent) :

    QMainWindow(parent),

    ui(new Ui::MainWindow)

{

    ui->setupUi(this);

     process1 = new QProcess(this);

//-----------------------------------------以下提供两种调用方式----------------------------------------------------//

//方式一:首先调用控制台,再通过控制台启动程序。(控制台:mac/linux下调用bash,windows下是cmd.exe)

     process1->start("bash");//调用控制台程序

     process1->waitForStarted();//等待程序确实启动再往下走

     process1->write("/usr/bin/python3.7 ./handpose.py \n");

//方式二:直接启动python,并要求他启动指定脚本。

     process1->start("/usr/bin/python3.7 /AR/ar/handpose.py");//直接启动python,并要求他启动指定脚本。

//---------------------------------------------------分割线-------------------------------------------------------------//

//信号槽连接,获取到程序输出就调用OnReadData函数

     connect(process1,SIGNAL(readyReadStandardOutput()),this,SLOT(OnReadData()));

}

void MainWindow::OnReadData(){

//打印输出

    QString strResult = QString::fromLocal8Bit(process1->readAllStandardOutput().data());

    qDebug() << strResult;

}

MainWindow::~MainWindow()

{

//杀死调用的进程

    process1->kill();

    process1->close();

    delete process1;

    delete ui;

}

输出问题: 值得指出的是,这里输出的内容,是当前py脚本运行结束后才会触发。比如脚本中有个循环10次每秒输出print,这里就不会触发10次分别打出print,而是会等10次运行结束后,统一打出文本。

解决办法:如果要想收到控制台的每次输出,可以再py脚本中将输出保存到内存中,或是剪切板,或者是指定的log文件,然后再通过qt读取,获取每次输出。

  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值