Qt调用Python函数

来源:互联网 发布:淘宝与天猫有什么区别 编辑:程序博客网 时间:2024/06/15 20:21

目标 

Qt调用Python函数

过程

Python底层是由C++编写的,二者间的相互调用是常见的操作。调用基本可分为extension和embedding两种,前者是Python程序为了提高运行速度加入C的扩展模块,后者则是C程序调用Python函数以利用其丰富的库函数和简洁的代码(另一种说法是省事儿),两种方法都在官网上有详细的介绍,具体的调用过程可以参考以下博客。此文主要记录调用numpy和release到测试机上遇到的问题。

问题

  1. Debug模式下PyImort_ImportModule()返回null,release正常
  2. PyParse_Turple()返回NULL
  3. PyImport_ImportModule第二次运行返回
  4. release到测试机上各种无法运行。

解决办法

  • 对于1/2,特别是python文件返回的不是python內建类型而是numpy之类的类型时常有发生,一般是python文件的路径问题导致无法import。如果是使用vs的话,可以观察输出栏,看编译过程是否将所需py文件包含进来。我在挣扎了一段时间后,决定还是不跟PyObjectArray死磕了,选择绕开numpy数组,在python函数返回前将ndarray通过toList()转为list数组,再在Qt一端使用PyList_GetItem()获取元素。提醒大家一点,调用的python脚本或者函数必须是在命令行直接使用python能够运行的,pycharm之类的IDE下不算。
  • Python代码
    return [mfcc_featMean.tolist(),mfcc_featStd.tolist(),mfcc_featEntropy.tolist(),timeLast]
  • C++代码
    frameNums = PyList_Size(PyList_GetItem(pReturn, 0));PyArg_Parse(PyList_GetItem(pReturn, 3), "d", &timeLast);double tmp;for (int i = 0; i < frameNums; i++){PyArg_Parse(PyList_GetItem(PyList_GetItem(pReturn, 0), i), "d", &tmp);mfcc_featMean.append(tmp);}


  • 对于3,查阅资料知一般不能重复import,否则读取的是上一次import的cache。时间问题也没有深究下去,直接在类内定义3个PyObject*成员变量,然后在类的构造函数进行初始化
    //python初始化Py_Initialize();pModule = PyImport_ImportModule("qtHelper");pFunc1 = PyObject_GetAttrString(pModule, "getMfccAndRes");pFunc2 = PyObject_GetAttrString(pModule, "getClassificationRes");
    那么这个类内就可以重复使用这个module和func了。
  • 对于4分为两种情况:一,提示错误:一般是缺少dll或相关文件。二,点击无反应:测试机需要安装python环境和要调用的库,使用shell测试一下py文件是否能运行。

参考链接

List Obeject python官方文档

C++和Python通信--知乎

c++调用python脚本遇到的那些坑