实验室做项目时遇到的工程问题,记录下来以备查用。Python底层是由C编写的,二者间的相互调用是常见的操作。调用基本可分为extension和embedding两种,前者是Python程序为了提高运行速度加入C的扩展模块,后者则是C程序调用Python函数以利用其丰富的库函数和简洁的代码。两种方法都在官网上有详细的介绍,具体的调用过程可以参考以下博客。此文主要记录调用numpy和release到测试机上遇到的问题。
问题描述
- Debug模式下PyImort_ImportModule()返回null,release正常
- PyParse_Turple()返回NULL
- PyImport_ImportModule第二次运行返回
- release到测试机上各种无法运行。
解决办法
问题1和2
python函数返回的不是python內建类型而是numpy之类的类型时常有发生,一般是python文件的路径问题导致无法import。如果是使用vs的话,可以观察输出栏,看编译过程是否将所需py文件包含进来。我在挣扎了一段时间后,决定还是不跟PyObjectArray死磕了,选择绕开numpy数组,在python函数返回前将ndarray通过toList()转为list数组,再在Qt一端使用PyList_GetItem()获取元素。注意一点,调用的python脚本或者函数必须是在命令行直接使用python能够运行的。 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*成员变量,然后在类的构造函数进行初始化,那么这个类内就可以重复使用这个module和func了。
#python初始化
Py_Initialize();
pModule = PyImport_ImportModule("qtHelper");
pFunc1 = PyObject_GetAttrString(pModule, "getMfccAndRes");
pFunc2 = PyObject_GetAttrString(pModule, "getClassificationRes");
问题4
分为两种情况:一,提示错误:一般是缺少dll或相关文件。二,点击无反应:测试机需要安装python环境和要调用的库,使用shell测试一下py文件是否能运行。