1 环境配置
1. Python和MFC的运行环境要一致,要么都是32位,要么都是64位,最好在最开始的时候就统一,不然之后的控件访问可能会出问题
2.添加环境变量
变量名:PYTHONPATH 变量值:Python安装目录/Lib
变量名:PYTHONHOME 变量值:Python安装目录
重启后环境变量生效
2 MFC配置
2.1 目录设置
项目-》属性-》VC++目录-》包含目录:python安装目录/include
项目-》属性-》C/C++-》常规-》附加包含目录:python安装目录/include
项目-》属性-》链接器-》常规-》附加库目录:python安装目录/libs
项目-》属性-》链接器-》常规-》附加库目录:python安装目录/Lib/site-packages(调用pip install导入的第三方库时需要添加)
项目-》属性-》链接器-》输入-》附加依赖项:python37.lib python37_d.lib
2.2 头文件
在调用的cpp文件中添加头文件
#include “Python.h”
3 MFC调用
Py_Initialize(); //1、初始化python接口
if (!Py_IsInitialized())
{
MessageBox(TEXT("未完成初始化"));
return;
}
//初始化使用的变量
PyObject* pModule = NULL;
PyObject* pFunc = NULL;
PyObject* pName = NULL;
//2、初始化python系统文件路径,保证可以访问到 .py文件
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
//3、调用python文件名。当前的测试python文件名是test2.py。在使用这个函数的时候,只需要写文件的名称就可以了。不用写后缀。不要用test作为名字,因为python本身有自己的test.py
pModule = PyImport_ImportModule("test2");
//4、调用函数
pFunc = PyObject_GetAttrString(pModule, "AdditionFc");
//5、给python传参数
PyObject* pArgs = PyTuple_New(2);//函数调用的参数传递均是以元组的形式打包的,2表示参数个数。如果AdditionFc中只有一个参数时,写1就可以了。这里只先介绍函数必须有参数存在的情况。
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 2)); //0:表示序号。第一个参数。
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 4)); //1:也表示序号。第二个参数。i:表示传入的参数类型是int类型。
//6、使用C++的python接口调用该函数
PyObject* pReturn = PyEval_CallObject(pFunc, pArgs);
//7、接收并提取python计算好的多个返回值
int numResult;
char* strResult;
PyArg_ParseTuple(pReturn, "i|s", &numResult, &strResult);
//8、结束python接口初始化
Py_Finalize();
4 可能的报错
4.1 无法打开python37_d.dll
把python37.dll复制一遍,重新命名为python37_d.dll,并在附加依赖项中加入python37_d.lib(不一定科学的解决方法)
4.2 无法解析的外部符号PyRun_SimpleString等
python和mfc的运行环境不一样,将运行环境都改成32位或都改成64位
4.3 Fatal Python error: unable to load the file system codec
添加python环境变量
4.4 PyImport_ImportModule返回值为NULL
调用函数PyObject_GetAttrString引发异常,报错信息如下图所示,结果发PyImport_ImportModule返回的pModule = NULL
其实只要把需要调用的python文件放在exe所在的文件夹就行了,且python文件名和函数名最好不要用test。
4.5 PyEval_CallObject返回值为NULL
查看python代码发现代码中import了第三方库,所以需要把库路径也加到包含目录里。
参考: