C++调用python2文件(Pyc)
最近做一个小的程序里面涉及用C++调用python2,其中有许多很坑的地方需要在这里提醒大家,避免的大家在走同样的弯路。这里以一个简单的demo做为例子
本文用的python环境是python 2.7.12
1编写TestAdd.py文件
代码如下:
def Hello():
print("Hello Python")
def Add(a,b):
return a+b
2.定位到Test.py的其所在目录,运行cmd生成TestAdd.pyc文件
在cmd中执行下面的命令就可以
python -m py_compile TestAdd.py
执行完成后在当前目录会生成TestAdd.pyc文件
3新建C++工程
本人用的是原生python而非Anaconda下的python,需要将python27下的include文件夹和libs文件夹拷贝到项目中
图
并且之前的py文件和pyc文件也要拷贝到项目中放在与Debug同级目录即可
4配置相关属性
右击项目点击属性–>链接器–>常规,配置附件库目录,这里加入是libs相对于生成exe的路径
这里需要注意的一点,将libs中的python27.lib重命名为python27_d.lib(这个的原因是include目录下的pyconfig.h里面的代码再debug下调用的是python27_d.lib)。否则会出现以下错误:
LINK : fatal error LNK1104: 无法打开文件“python27_d.lib”
在属性–>链接器–>输入中的附加依赖项,添加python27_d.lib
6编写pythontest.cpp文件
代码如下:
#include <iostream>
#include "include/Python.h"
using namespace std;
void Hello()
{
Py_Initialize();
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
pModule = PyImport_ImportModule("TestAdd");
pFunc = PyObject_GetAttrString(pModule, "Hello");
PyEval_CallObject(pFunc, NULL);
Py_Finalize();
}
void Add(int a1,int a2) {
Py_Initialize();
PyObject* pModule = NULL;
PyObject* pFunc = NULL;
pModule = PyImport_ImportModule("TestAdd");
pFunc = PyObject_GetAttrString(pModule, "Add");
//创建参数
PyObject* pArgs = PyTuple_New(2);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a1));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", a2));
//返回值
PyObject* pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs);
//将返回值转换为int类型
int result;
PyArg_Parse(pReturn, "i", &result);
cout << "a1+a2=" << result << endl;
Py_Finalize();
}
int main() {
cout << "调用TestAdd.py中的Hello函数..." << endl;
Hello();
cout << "调用TestAdd.py中的Add函数..." << endl;
Add(6, 8);
getchar();
return 0;
}
执行结果
关于代码部分,首先是添加python的声明
#include “Python.h”
然后是对python接口的初始化
Py_Initialize();
初始化变量,这里的变量主要是调用的py文件,调用的方法
PyObject * pModule = NULL;
PyObject * pFunc=NULL;
调用py文件名以及调用方法
pModule = PyImport_ImportModule("TestAdd");
pFunc = PyObject_GetAttrString(pModule, "Add");
创建参数
PyObject* pArgs = PyTuple_New(2);//函数调用的参数传递均是以元组的形式打包的,2表示参数个数
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a1));//传入第一个参数
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", a2));//传入第二个参数
使用C++调用python接口
PyObject* pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs);
用C++变量接收返回值
int result;
PyArg_Parse(pReturn, "i", &result);
结束调用python接口
Py_Finalize();
关于C++与python之间的数据转换的代码
这里对应的就是上面代码中Py_BuildValue和PyArg_Parse的参数
参考文章
【1】https://blog.youkuaiyun.com/stq054188/article/details/82012901
【2】https://www.cnblogs.com/apexchu/p/5015961.html
【3】https://blog.youkuaiyun.com/qq_32716885/article/details/80651433