VS2019+Qt msvc2017+python第三方库调用可传参

本意目的是通过qt窗口调用python脚本,使用nltk提取文章关键字,配置了一天,记录如下。

1.#include <Python.h>

首先需要明确,qt的位数(msvc的位数)一定要和python位数相同,若不相同会提示:

·“x86与计算机当前模块x64不符” 

·或明明选了libs文件夹还报错“未能解析的外部符号”LINK2019这种错误,也是位数不同导致的

其次vs2019里选择对应python解释器的include和libs目录,为头文件和链接库提供路径。

 然后按网上大家说的,修改python文件夹下include/object.h中400行左右的地方(搜索slot即可),添加这两句

接着进入python文件夹下的libs文件夹,把python37.lib复制一份重命名python37_d.lib

此时在qt头文件里打上 #include <Python.h>,f5运行可行

2.第三方库的调用

无传参helloworld示例

有传参示例如下:

#include "trytrypython.h"

trytrypython::trytrypython(QWidget* parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);


	//进行初始化
	Py_Initialize();
	//如果初始化失败,返回
	if (!Py_IsInitialized())
	{
		qDebug() << "IsInitialized: error";
	}
	//导入trydata.py文件,放在exe同文件夹
	PyObject* pModule = PyImport_ImportModule("trydata");

	if (!pModule)
	{
		qDebug() << "ImportModule: error";
	}
	//调用其中的add函数求和
	PyObject* pFuncHello = PyObject_GetAttrString(pModule, "add");
	//如果失败则返回
	if (!pFuncHello)
	{
		qDebug() << "GetAttrString: error";
	}
	else {
		PyObject* args = PyTuple_New(2);
		PyObject* arg1 = PyLong_FromLong(11111);
		PyObject* arg2 = PyLong_FromLong(22222);
		PyTuple_SetItem(args, 0, arg1);
		PyTuple_SetItem(args, 1, arg2);
		PyObject* result = PyObject_CallObject(pFuncHello, args);
		if (result)
		{
			long a = PyLong_AsLong(result);
			qDebug() << "a:" << a << endl;
		}

	}
	//调用函数
	//PyObject_CallFunction(pFuncHello, NULL);
	//退出
	Py_Finalize();
}

我是没有进行任何操作,直接在代码中import nltk以及其他包,便可使用分词筛词等功能

第二天后记:

        1.传参时使用“类型”来满足多种类型的传参

PyObject *pArgs = PyTuple_New(3);
PyObject* arg1 = Py_BuildValue("i",220);  //整数参数
PyObject* arg2 = Py_BuildValue("f", 3.14);  //浮点数参数
PyObject* arg3 = Py_BuildValue("s", "hello"); //字符串参数

PyEval_CallObject(pFunc, pArgs); //调用函数,pArgs元素个数与被调函数参数个数一致

        其他形式传入参数,或用Pyxx_fromyy(与as相对应)变换,如下

        2.python返回值时不知道为什么无法使用PyList_Check(retvalue)来判断返回值的类型,但这个值仍然可以使用其类型的对应操作如list用PyList_GetItem()等,故传字符串时不知道对面过来的究竟是什么东西,最后python里字符串是unicode形式,需要先转为utf8,也就是python的bytes形式,再用PyBytes_AsString()来读取为char[ ],(该函数是char * PyString_AsString(PyObject*)的更新),或者在python端就把str转为bytes再return,两种方法都可以正常收回返回值字符串。方法一如下:

/*nltk.freq()的数据结构是这样的:
[0:('appl', 12)
1:('banana', 7)
2:('orang', 6)
3:('paint', 5)
4:('call', 2)]

list里套tuple套str和int,我只想要str*/
PyObject* result=PyObject_CallObject(pFuncGetKeyword, args);
		int SizeOfList = PyList_Size(result);//List对象的大小
		for (int i = 0; i < SizeOfList; i++)
		{
			PyObject* ListItem = PyList_GetItem(result, i);//获取List对象中的每一个元素
			printf("%s", PyBytes_AsString(PyUnicode_AsUTF8String(PyTuple_GetItem(ListItem, 0))));
			//Py_DECREF(ListItem); //释放空间
		}

最后可以成功用了下面这些包,返回了一个多层嵌套的list到qt主线程作为char[ ]打印

读了挺久的python文档,上面有c++调用python用例,下面有具体的交互函数

网上有说要把对应的site-package里的包复制到exe同文件夹下的,不行的可以试试

复制sitepackage:QT(msvc2015_64)调用Python3脚本过程记录

 

3.其他小插曲

电脑更改过用户名,原来C盘下默认路径的python内路径一片狼藉,删除后(控制面板方法)重新下载(找到了原来的下载包),CMD内:python -m pip install nltk 提示我已经安装了nltk,而import nltk报错:

No module named 'regex._regex

 python -m pip install nltk重新安装依然无果

删除regex包重新安装,成功,之前在anaconda里下载过nltk数据包(本次这个python是单独的32位),其nltk_data文件夹路径在c盘是共享的,尝试stopwords等数据,成功分词并提取词干。

若没下载过nltk的,import nltk后

nltk.download()

从可视窗口下载即可 

*第三天后记:

        出现了第一个问题是重复import_module一个py文件,nltk不允许重复import会报错,不知道其他库怎么样,故调整为在qt界面开始就打开py解释器,打开py文件,后续需要调用函数时再去单独调用函数,避免了重复import nltk

        第二个问题是无法多次(6次以上)使用python函数进行nltk分析,后发现原因是

        PY_DECREF这玩意不仅p用没有还不让我大量调用,没时间研究具体原理是啥,全部注掉,心情愉悦~ 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值