C++调用python (2.7版本)
由于个人偏好喜欢用python写代码,尤其是数据处理等,最近想试试在VS2013里,直接调用python中的曲线拟合函数。作为小白,由于之前完全没接触过,就一直找网上找教程,折腾了2小时总算是搞定了。接下来,为了方便和我一样的初学者学习,我将具体的配置过程详细写下来,写得不好,还望指教。(一个月后:现在看来,不建议这样调用,个人觉得意义不大,若想学一下,可以继续浏览;否则还是放弃直接多看会儿C++,还是能将python代码直接改成C++代码的,不用调用)
一、 最终结果展示:
以下代码是main.cpp
#include <iostream>
#include <Python.h>
using namespace std;
extern "C"
{
#include "Python.h"
}
//调用输出"Hello Python"函数
void Hello()
{
Py_Initialize();//调用Py_Initialize()进行初始化
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
pModule = PyImport_ImportModule("Test001");//调用的Python文件名
pFunc = PyObject_GetAttrString(pModule, "Hello");//调用的函数名
PyEval_CallObject(pFunc, NULL);//调用函数,NULL表示参数为空
Py_Finalize();//调用Py_Finalize,和Py_Initialize相对应的.
}
//调用Add函数,传两个int型参数
void Add()
{
Py_Initialize();
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
pModule = PyImport_ImportModule("Test001");//Test001:Python文件名
pFunc = PyObject_GetAttrString(pModule, "Add");//Add:Python文件中的函数名
//创建参数:
PyObject *pArgs = PyTuple_New(2);//函数调用的参数传递均是以元组的形式打包的,2表示参数个数
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 6));//0--序号,i表示创建int型变量
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 8));//1--序号
//返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs);//调用函数
//将返回值转换为int类型
int result;
PyArg_Parse(pReturn, "i", &result);//i表示转换成int型变量
cout << "6 + 8 = " << result << endl;
Py_Finalize();
}
int main(int argc, char** argv)
{
cout << "调用Test001.py中的Hello函数..." << endl;
Hello();
cout << "\n调用Test001.py中的Add函数..." << endl;
Add();
system("pause");
return 0;
}
接着是调用的函数,也就是Test001.py文件中内容:
def Hello():
print("Hello Python")
def Add(a, b):
return a+b
最后,运行结果如下:
二、环境配置
那么究竟如何调用呢?我的电脑环境:Win7(64位)+anaconda2.4(python2.7.13)+VS2013,其实我习惯用anaconda3.4.2(python3.5),起初用C++去调用python3.5,遇到太多的坑,实在不行,按照同样的方法试了一下python2.7,真的没问题,欲哭无泪。。。下面我再调用一次,具体步骤如下:
1、python2.7的安装(anaconda2-4.4.0-Windows-x86_64),并配置环境变量(否则报错no module named sites);
2、将Python加到VS2013的详细过程:
(1)桌面上新建一个文件夹,如test,再建立一个空的Win32控制台项目,创建main.cpp保存test文件夹中,此时的代码会报错,因为还没导入python2.7的头文件路径与库文件的路径;
(2)找到python2.7的安装路径:(我的是:D:\python2.7\anaconda2.4),找到路径下的include与libs两个文件夹,将libs中的python27.lib复制并更名为python27_d.lib;
(3)x64平台&python2.7头文件与库文件的路径配置:
X64平台:生成->配置管理器->新建;
右击进入属性设置页C/C++->常规->附加包含目录,输入 D:\python2.7\anaconda2.4\include
再找到链接器->常规->附加目录项,输入 D:\python2.7\anaconda2.4\libs
结果如下图所示:
(4)生成解决方案,显示:
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
(5)别激动,先运行,你会发现,报错啦!!!无法启动此程序,因为计算机中丢失python27.dll。尝试重新安装该程序以解决此问题。怎么办呢?
将python安装路径下的python27.dll拷贝到桌面test文件夹中的x64文件夹中的Debug目录下
(如:C:\Users\Zhangwei\Desktop\test\ConsoleApplication1\x64\Debug):
(6)重新生成解决方案,并运行,还是报错了,气不气?如下图:
(7)之所以报错,是因为还未添加Test001.py,将该文件添加到Debug路径下
(如:C:\Users\Zhangwei\Desktop\test\ConsoleApplication1\x64\Debug):
(8)重新生成解决方案,再次运行,很激动吧,终于成功咯!!!
注意:建议别按照上面的方式更改坏境变量,否则在pycharm中选择相应的python2.7版本时候,会报错。
相信走到这里,C++调用python应该是问题不大,至少语法上是没有问题的,接下来我再说说我遇到的bug:
由于我习惯用python3.5,之前用VS2013调用python3.5,若按照上面这一套流程走下来,还是无法运行,真的是心累!我怀疑是anaconda3.4.2(python3.5.2)里面的libs中的文件只有三个,是不是有缺失?
后来 经过查找相关资料,总算是找到了调用解决方案,现在总结如下:
C++调用python (3.5版本)
VS2013+python3.5
一、最终结果展示
#include <iostream>
#include <Python.h>
using namespace std;
//extern "C"
//{
//#include "Python.h"
//}
// 练习一:如何使用C++调用函数python中的参数返回函数?
int great_function_from_python(int a)
{
Py_SetPythonHome(L"C:/Users/Zhangwei/Anaconda3");//配置python3的环境变量
Py_Initialize();
int res;
PyObject *pModule, *pFunc;
PyObject *pArgs, *pValue;
/* import */
//pModule = PyImport_Import(PyString_FromString("great_module"));
pModule = PyImport_ImportModule("great_module");
/* great_module.great_function */
pFunc = PyObject_GetAttrString(pModule, "great_function");
/* build args */
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a));
/* call */
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs);
PyArg_Parse(pReturn, "i", &res);//i表示转换成int型变量
return res;
Py_Finalize();
}
// 练习二:如何使用C++直接运行hello!
void print()
{
Py_SetPythonHome(L"C:/Users/Zhangwei/Anaconda3");//配置python3的环境变量
//Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("print('Hello Python!')\n");
Py_Finalize();
}
// 练习三:如何使用C++调用curveFitting.py中的函数Hello
void Hello() //调用输出"Hello Python"函数
{
Py_SetPythonHome(L"C:/Users/Zhangwei/Anaconda3");//配置python3的环境变量
Py_Initialize();//调用Py_Initialize()进行初始化
if (!Py_IsInitialized())
{
printf("初始化失败!");
}
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
pModule = PyImport_ImportModule("curveFitting");//调用的Python文件名
pFunc = PyObject_GetAttrString(pModule, "Hello");//调用的函数名
PyEval_CallObject(pFunc, NULL);//调用函数,NULL表示参数为空
Py_Finalize();//调用Py_Finalize,和Py_Initialize相对应的.
}
//练习四:如何使用C++调用curveFitting.py中的函数Add
void Add() //调用Add函数,传两个int型参数
{
Py_SetPythonHome(L"C:/Users/Zhangwei/Anaconda3");//配置python3的环境变量
//第一步:调用Py_Initialize()进行初始化
Py_Initialize();
//检查初始化是否完成
if (!Py_IsInitialized())
{
printf("初始化失败!");
}
//py文件及函数声明变量
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
//加载
try
{
pModule = PyImport_ImportModule("curveFitting");//curveFitting:Python文件名
}
catch (...)
{
printf("pModule加载异常!");
}
if (pModule == NULL)
{
printf("pModule加载失败!");
}
pFunc = PyObject_GetAttrString(pModule, "Add");//Add:Python文件中的函数名
//创建参数:
PyObject *pArgs = PyTuple_New(2);//函数调用的参数传递均是以元组的形式打包的,2表示参数个数
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 6));//0--序号,i表示创建int型变量
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 8));//1--序号
//返回值
PyObject *pReturn = NULL;
pReturn = PyEval_CallObject(pFunc, pArgs);//调用函数
//将返回值转换为int类型
int result;
PyArg_Parse(pReturn, "i", &result);//i表示转换成int型变量
cout << "6 + 8 = " << result << endl;
Py_Finalize();
}
int main(int argc, char *argv[]) {
//练习一:
printf("运行结果为:%d\n", great_function_from_python(2));
//练习二
printf("\n");print();
//练习三
printf("\n");
cout << "调用curveFitting.py中的Hello函数..." << endl;
Hello();
//练习四
printf("\n");
cout << "\n调用curveFitting.py中的Add函数..." << endl;
Add();
system("pause");
return 0;
最后的运行结果如下:
二、环境配置
如果试过第一种方法的朋友会发现,直接更改系统环境变量,会导致原本的python2.7运行始终报错。以python3.5为例:需要单独将anaconda3下面的,include文件夹里面的头文件、libs文件夹里面的库函数,以及python35.dll(动态链接库文件)都单独拷贝出来,至于怎么设置,怎么放,咱们慢慢来。
1、桌面新建一个文件夹,取名为test_python35;
2、将anaconda3下面的,include文件夹、libs文件夹都拷贝到test_python35文件夹中;
3、打开VS2013,新建一个项目,选好路径,桌面的文件夹test_python35里面的内容如下:
4、新建一个main函数如上展示图所示,接下来需要配置环境变量
(1)添加头文件
(2)添加库文件
(3)代码中配置python3的环境变量
Py_SetPythonHome(L"C:/Users/Zhangwei/Anaconda3");//配置python3的环境变量
5、生成解决方案,不会报错,但肯定没有结果,因为还没有添加动态链接库文件调用的python原函数。具体做法:在生成的Debug路径下添加python35.dll(anaconda3的安装路径里面有)、调用的python原函数(curveFitting.py与great_module.py),如下图所示
6、重新生成解决方案,再次运行即可,于是便得到了最开始的结果图。
三、C++调用python的代码解读
这部分多查阅相关文件,很快就能上手的 ,具体就不说了,网上一大把,最后祝大家学业有成。
PS:以上代码已打包,下载链接为C++调用python3.5或者http://download.youkuaiyun.com/download/zichen_ziqi/10236034。
参考文献
1. C++调用python实例:http://blog.youkuaiyun.com/u012983289/article/details/55194714
2. VS平台简单实用C++调用python3.5的方法:http://blog.youkuaiyun.com/polley88/article/details/54971560
3. python实例浅谈三之C++与python相互调用: http://blog.youkuaiyun.com/taiyang1987912/article/details/44779719
4. C++调用python3:http://blog.youkuaiyun.com/lisy14/article/details/64498796
5. C++调用python3:http://blog.youkuaiyun.com/u014794992/article/details/52901219