C++调用python (2.7版本)

(Win7_64 + VS2013 + python2.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.csdn/download/zichen_ziqi/10236034。


参考文献

1.  C++调用python实例:http://blog.csdn/u012983289/article/details/55194714

2.  VS平台简单实用C++调用python3.5的方法:http://blog.csdn/polley88/article/details/54971560

3. python实例浅谈三之C++与python相互调用: http://blog.csdn/taiyang1987912/article/details/44779719

4.  C++调用python3:http://blog.csdn/lisy14/article/details/64498796

5.  C++调用python3:http://blog.csdn/u014794992/article/details/52901219



更多推荐

混合编程之——C++调用python2.7&python3.5