C++调用python方法

python语言有着很强大的第三方支持,并且程序简单,易于编写。在一些应用情况,如excel自动化上,C++由于相关的支持库很难找到,所以考虑到调用现成的python库实现相关功能。但题主经过搜索发现这种接口制作的相关资料比较少,因此希望能尽绵薄之力,做一点贡献,希望能够帮助到后来者。过程中难免有些错误,望能体谅指正。

1 环境配置

基本环境:VS2019 + python3.7.6

1.1 安装python

安装过程略了,相关的版本官网上都有,安装过程也是一路点下来就行了。
注意:安装的python要和编译环境保持一致,具体而言就是两点:
— 32位对32位,64位对64位
— 默认的python安装包是具有release库的,但是没有debug库,如果想要debug,需要在安装python的时候多勾选一项

在这里插入图片描述

1.2 VS2019的属性配置

主要是几个部分:
VS2019里:
工程属性 >VC++目录>包含目录 填入python安装目录下的include文件夹
工程属性 >VC++目录>库目录 填入python安装目录下的libs文件夹
工程属性 > 链接器 > 输入>附件依赖项 填入python安装目录下的libs文件夹里的lib文件

1.3 调用头文件

在使用的时候需要include一个python.h的头文件

2 调用方法

下面的内容主要转载自https://blog.csdn.net/yangjf91/article/details/93062961

2.1 常用函数:

功能函数
初始化Python环境Py_Initialize()
添加模块路径(或者说脚本路径)PyRun_SimpleString()
导入模块PyImport_ImportModule()
导入函数PyObject_GetAttrString()
使用函数PyObject_CallObject()
获取结果PyArg_Parse()
结束释放Py_DECREF()、Py_Finalize()

2.2 常用指针

PyObject* 这是一个相当常用的指针了。
这个指针能存储任意类型的python变量(包括整型,浮点型,字符串,列表,字典等等),还能存储一些调用的对象,如模块等。

2.3 调用过程

  1. 初始化Python环境
	//< 设置python的路径并初始化运行环境
	Py_SetPythonHome(L"E:/python");
	Py_Initialize();

	//< 定位调用模块路径,便于后面调用模块
	PyRun_SimpleString("import sys");
	//添加Insert模块路径  
	PyRun_SimpleString("sys.path.append('D:/pythonfile')");
  1. 添加导入的模块
	//< 接着上面已经定位好的模块路径,直接调用需要的模块(这里是Test模块)
	PyObject* pModule = PyImport_ImportModule("Test");
	if (pModule == NULL)
	{
		//< 如果模块调用失败,则返回false 
		std::cout << "Import Failed!" << std::endl;
		return false;
	}
  1. 调用函数
	//< 声明两个输入参数
	PyObject* Params = PyTuple_New(2);
	//< 传入两个python函数的输入参数
	PyObject* Param1 = Data;
	PyObject* Param2 = Statistics;
	//< 封装输入参数
	PyTuple_SetItem(Params, 0, Param1);
	PyTuple_SetItem(Params, 1, Param2);
	//< 调用func函数,并传入参数,FuncRes为函数的返回值
	PyObject* PyFunc = PyObject_GetAttrString(pModule, "func");
	PyObject* FuncRes = PyEval_CallObject(PyFunc , Params);
  1. 结果释放
	//< 没啥好说的
	Py_Finalize();

3 数据转化

介绍几个常用的函数

3.1 C++转python

介绍一个十分好用的函数,Py_BuildValue(),用来将C++的数据转换成python类型的数据,返回一个PyObject的指针,支持字符串,整形,浮点型等类型转化,甚至还能建立python中的列表,字典等。使用方法见下表

命令实际输入
Py_BuildValue("")None
Py_BuildValue(“i”, 123)123
Py_BuildValue(“iii”, 123, 456, 789)(123, 456, 789)
Py_BuildValue(“s”, “hello”)‘hello’
Py_BuildValue(“ss”, “hello”, “world”)(‘hello’, ‘world’)
Py_BuildValue(“s#”, “hello”, 4)‘hell’
Py_BuildValue("()")()
Py_BuildValue("(i)", 123)(123,)
Py_BuildValue("(ii)", 123, 456)(123, 456)
Py_BuildValue("(i,i)", 123, 456)(123, 456)
Py_BuildValue("[i,i]", 123, 456)[123, 456]
Py_BuildValue("{s:i,s:i}", “abc”, 123, “def”, 456){‘abc’: 123, ‘def’: 456}
Py_BuildValue("((ii)(ii)) (ii)", 1, 2, 3, 4, 5, 6)(((1, 2), (3, 4)), (5, 6))

在进行字符串转换时,需要注意两个问题:
1.Py_BuildValue()支持的是char*
2.字符串的编码问题,C++中字符串的默认编码方式是ASCII码,但在python中的编码方式为utf-8编码,因此存在着中文转码的问题。对于存在中文的字符串如CString,推荐使用下面的方法,亲测有效

	CString DataCStr = _T("2020-09-17");
	DWORD dwNum = WideCharToMultiByte(CP_UTF8, NULL, DataCStr, -1, NULL, NULL, NULL, NULL);
	char* Mychar = new char[dwNum];
	WideCharToMultiByte(CP_UTF8, NULL, DataCStr, -1, Mychar, dwNum, NULL, NULL);
	PyObject* temp = Py_BuildValue("s", Mychar);

3.2 python转C++

通常是读取python模块中的返回值,进而将PyObject*类型转化为对应的C++数据类型。
几个函数(更多的可以百度一下,这部分内容很多)这个太明显了,就不解释了。

long PyLong_AsLong(PyObject *pylong)

double PyFloat_AsDouble(PyObject *pyfloat)

3.3 列表处理

3.3.1 建立列表

PyObject* PyList_New(int)

输入参数: 建立列表的长度
返回值: PyObject类型的指针,指向新创建创建的列表

Tips:如果建立空列表,可以将输入参数置为零

3.3.2 append列表

PyList_Append(PyObject* param1,PyObject* param2)

输入参数:
param1: 原列表
param2: 需要加在列表末尾的内容

3.3.3 获取列表长度

ssize_t PyList_Size(PyObject *)

返回值:列表长度
输入参数:需要获得长度的列表

3.3.4 获取列表中指定位置的数据

(PyObject *) PyList_GetItem(PyObject *, Py_ssize_t)

输入参数:
PyObject * 对应列表
Py_ssize_t 偏移量
返回值:
对应位置的元素

4 目前遇到的几个问题

4.1 Py_Initialize()报错

初始化调用Py_Initialize()就报错,网上关于这个问题都是检查python版本有没有问题,路径是否设置对。最后通过C++调用Python Py_Initialize失败解决了问题,即添加Py_SetPythonHome(L"<Python路径>"),也就是前面的2.2节中“初始化Python环境”中的第一句(实际上,这句有时候不加也是好使的,好使的情况可能是因为设置了环境变量,但是为了保险,还是加上这句)。

4.2 error LNK2001: 无法解析的外部符号 __imp_Py_Initialize

这种情况通常是VS中配置的环境与python中的不符,常见的比如:VS中的编译环境是32位的,而python安装的是64位的。所以,解决办法就是,要么换个python版本,要么配置合适的VS编译环境。

4.3 LNK1104 无法打开文件“python37_d.lib”

这个问题就是你在VS中用了debug版本,但在安装python的时候却没安装debug包,这种问题你只要在安装的时候加入debug包,并在附加依赖项中加入相关的lib文件就行了,debug包勾选如1.1节中的介绍
详细内容参见:https://blog.csdn.net/weixin_43788499/article/details/84933210

5 参考链接

  1. C++调用Python总结
    https://blog.csdn.net/yangjf91/article/details/93062961
  2. C++调用Python脚本中的函数
    https://www.cnblogs.com/betterwgo/p/8176525.html
  3. LNK1104 无法打开文件“python37_d.lib”问题处理
    https://blog.csdn.net/weixin_43788499/article/details/84933210
  4. WideCharToMultiByte 函数使用说明
    https://www.cnblogs.com/zhoudingcocng/p/6433960.html
  5. 编码格式介绍
    https://blog.csdn.net/byf0521hlyp/article/details/80365045
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值