c++调用python方法总结

为了后面编程学习的方便,这篇文章主要讲解c++如何调用python。

1.目的与环境

目的:

~略

搭环境的意义:

怎么安装语言包就不解释了,自行查阅吧,为了好写文章,我就在window上用vs2013演示。此处重点说下对于vs2013的环境配置(这个并不是针对python特有的,甚至不是针对vs特有的,调用第三方库或工具的配置思路其实都类似)(ps:不配置的话vs2013在编译的时候就找不到python(我用的2.7版本)具体的头文件定义和对应lib文件,这里只简单提一下原因,还有dll什么的以后再详解)。

配置具体过程:

(1)方法一:直接项目配置

Step1:添加头文件引用目录

C/C++ -> General -> Additional Include Directories

在Additional include dir..中添加自己系统中python头文件目录(include)

Step2:添加库文件目录

同理,Linker -> General -> Additional Library

在Additional Library中添加自己系统python的libs目录(一般和incude在同级目录下)

Step3:测试

Ok,我们测试下配置是否成功~~

先写一个简单的python代码。

新建xiaowu.py文件,内容如下:

#coding=utf-8

def printHello():

print ‘主人您好,初次见面,我是您的仆人叶儿~从今往后,我会永远陪伴在您身边,在你的灵魂里’

 

新建main.cpp文件,内容如下:

#include<iostream>

#include “Python.h”  //前面所做的一切配置都是为了能正常使用这个头文件和对应库

using namespace std;

int main()

{

Py_Initialize();//使用python之前,要调用Py_Initialize(),这个函数初始化python环境

PyObject * pModule = NULL;//声明变量

PyObject * pFunc = NULL;// 声明变量

pModule = PyImport_ImportModule(“sun”);//导入要调用的python文件名

if (nullptr == pModule)

{

cout << “文件读取失败” << endl;

exit(-1);

}

pFunc = PyObject_GetAttrString(pModule, “printHello”);//取得文件中的某个函数

PyEval_CallObject(pFunc, NULL);//调用这个函数

Py_Finalize();//结束python环境

return 0;

}

运行结果:

 

说明配置成功~~

 

(2)方法二:设置独立配置文件

props/vsprops:工程属性表文件(project property sheet),然后在项目中加载。后者为vs2008的,前者为vs2010及以后版本的,其主要包含工程属性配置相关,可以单独提取出来供不同工程项目公共使用,此外不同项目还可以追加、修改该继承(加载)的属性表,其他引用了该公共属性表的工程不受到影响;此属性表文件可以节省配置时间开销、减少配置错误率,减少工程的重复设置,最终只要设置一次就可以了,尤其是当解决方案下有很多的工程需要修改配置时,其效果显而易见。

使用工程属性表:

操作类似于创建过程;

一: 打开菜单栏View(视图)下的Property Manager(属性管理器),此时出现的属性管理器面板属性页;

二:展开需要添加属性表的工程项目,并对需要添加属性的Debug、Release以及相应的Win32和x64位的版本属性中,右键添加现有属性表,将之前创建的属性表添加进去。

重定义自己的工程属性:

在添加了该属性表后,可根据需要修改项目工程属性,如增加、修改、删除等操作(对原添加的属性表无影响),若直接修改添加的属性表也可以,不过若该属性表为其他工程项目共享的(文件位置),则会影响其他工程的属性表配置的,故一般情况下若某工程特殊需要,则只需要修改当前工程属性即可而不是属性表。

创建属性表如上图所示

实际目录中,多出了一个.props文件,内容如下

<?xml version=”1.0″ encoding=”utf-8″?>

<Project ToolsVersion=”4.0″ xmlns=”http://schemas.microsoft.com/developer/msbuild/2003″>

<ImportGroup Label=”PropertySheets” />

<PropertyGroup Label=”UserMacros” />

<PropertyGroup />

<ItemDefinitionGroup>

<ClCompile>

<AdditionalIncludeDirectories>D:\visual Leak Detector\SetUp\Visual Leak Detector\include;%(AdditionalIncludeDirectories);D:\python3\python2.7\include;</AdditionalIncludeDirectories>

</ClCompile>

<Link>

<AdditionalLibraryDirectories>D:\visual Leak Detector\SetUp\Visual Leak Detector\lib\Win32;%(AdditionalLibraryDirectories);D:\python3\python2.7\libs;</AdditionalLibraryDirectories>

</Link>

</ItemDefinitionGroup>

<ItemGroup />

</Project>

 

 

2.我们可能会碰到的问题

编译错误:

LINK : fatal error LNK1104: cannot open file ‘python27_d.lib’ ,我使用的是python2.7.15,解决方法是进入libs文件中复制python27_.lib改名为python27_d.lib(强行改的节奏),这种方式我在python-3.5.0中没有成功,最好的方式还是下载源码编译debug版本)。

链接错误:

python是32位还是64位需与vs的solution platform一致,否则:

1>main.obj : error LNK2019: unresolved external symbol __imp__PyObject_GetAttrString referenced in function _main

1>main.obj : error LNK2019: unresolved external symbol __imp__Py_Initialize referenced in function _main

1>main.obj : error LNK2019: unresolved external symbol __imp__Py_Finalize referenced in function _main…

查看python的位数:

Visual studio platform版本:

PyImport_ImportModule返回NULL:

要重点注意的是,python脚本不能有什么语法错误,要不然c++调用PyImport_ImportModule会返回NULL。还要注意调用的.py文件的路径,若读取不到也会返回NULL。

 

3调用方法

直接调用python语句

#include<iostream>

#include “Python.h”  //前面所做的一切配置都是为了能正常使用这个头文件和相关库

using namespace std;

int main()

{

Py_Initialize(); //使用python之前,要调用Py_Initialize(),这个函数初始化python环境

PyRun_SimpleString(“print ‘小五哥哥'”);  //直接调用python语句

Py_Finalize();      //释放资源,结束python环境

return 0;

}

 

加载 Python 模块并调用函数

见测试代码

 

c++向python文件传递参数

Python 的参数实际上是元组,因此传参实际上就是构造一个合适的元组。

常用的有两种方法:

  • 使用 PyTuple_New 创建元组, PyTuple_SetItem 设置元组值

PyObject* args = PyTuple_New(3);

PyObject* arg1 = Py_BuildValue(“i”, 100); // 整数参数

PyObject* arg2 = Py_BuildValue(“f”, 3.14); // 浮点数参数

PyObject* arg3 = Py_BuildValue(“s”, “hello”); // 字符串参数

PyTuple_SetItem(args, 0, arg1);

PyTuple_SetItem(args, 1, arg2);

PyTuple_SetItem(args, 2, arg3);

  • 直接使用Py_BuildValue构造元组

PyObject* args = Py_BuildValue(“(ifs)”, 100, 3.14, “hello”);

PyObject* args = Py_BuildValue(“()”); // 无参函数

具体参见官方文档

 

单个参数传递

代码实例:

#include<iostream>

#include “Python.h”  //前面所做的一切配置都是为了能正常使用这个头文件和相关库

using namespace std;

int main()

{

Py_Initialize();//使用python之前,要调用Py_Initialize(),这个函数初始化python环境

PyObject * pModule = NULL;//声明变量

PyObject * pFunc = NULL;// 声明变量

PyObject*pArg = NULL; //参数指针

pModule = PyImport_ImportModule(“xiao”);//导入要调用的python文件名

if (nullptr == pModule)

{

cout << “文件读取失败” << endl;

exit(-1);

}

pFunc = PyObject_GetAttrString(pModule, “Hello”);//取得文件中的某个函数

pArg = Py_BuildValue(“(s)”, “xiaowugege”);  //一个字符串参数

PyEval_CallObject(pFunc, pArg);//调用这个函数(第二个形参就是参数传递入口

Py_Finalize();      //释放资源,结束python环境

return 0;

}

xiao.py文件内容:

def Hello(s):

print(“hello,”+s)

 

元组参数传递

Demo.py文件内容

def Add(a,b):

print(“{0}”.format(a+b))

 

#include<python.h>

int main()

{

Py_Initialize();

if(!Py_IsInitialized())

{

printf(“PythonInit failed!\n”);

return0;

}

PyObject*pModule = NULL;

PyObject*pFunc = NULL;

PyObject*pArg = NULL;

pModule= PyImport_ImportModule(“Demo”);

pFunc= PyObject_GetAttrString(pModule,”Add”);          //两个整形的参数

pArg= PyTuple_New(2);                                  //确定Add函数两个参数

PyTuple_SetItem(pArg,0,Py_BuildValue(“i”,2));          //向元组中添加内容

PyTuple_SetItem(pArg,1,Py_BuildValue(“i”,3));

PyEval_CallObject(pFunc,pArg);   //调用函数并传参

Py_Finalize();

Return0;

}

 

列表参数传递

def printList(l):

print len(l)

for var in l:

print var

 

#include<python.h>

int main()

{

Py_Initialize();

if(!Py_IsInitialized())

return0;

PyObject*pModule = PyImport_ImportModule(“Demo”);

PyObject*pyFunc_printList = PyObject_GetAttrString(pModule,”printList”);

if(pModule&& PyCallable_Check(pyFunc_printList))

{

PyObject*pyParams = PyList_New(0);           //初始化一个列表

PyList_Append(pyParams,Py_BuildValue(“i”,5));//列表添加元素值

PyList_Append(pyParams,Py_BuildValue(“i”,2));

PyList_Append(pyParams,Py_BuildValue(“i”,6));

PyList_Append(pyParams,Py_BuildValue(“i”,8));

PyObject*args = PyTuple_New(1);           //将列表转换成元组的一个元素后传递给Python程序

PyTuple_SetItem(args,0,pyParams);

PyEval_CallObject(pyFunc_printList,args);

}

Py_Finalize();

Return0;

}

 

类参数传递

class Person:

def __init__(self, name):

self.name = name

def printName(self):

print self.name

 

#include<python.h>

int main()

{

Py_Initialize();

if(!Py_IsInitialized())

return0;

PyObject*pModule = NULL;

PyObject*pFunc = NULL;

PyObject*pArg = NULL;

PyObject*pClass = NULL;

PyObject*pObject = NULL;

 

pModule= PyImport_ImportModule(“Demo”);

pClass= PyObject_GetAttrString(pModule,”Person”);   //先获取类名

pArg= PyTuple_New(1);

PyTuple_SetItem(pArg,0,Py_BuildValue(“s”,”xiaowu”));

pObject=PyEval_CallObject(pClass,pArg);              //根据类名实例化对象

pFunc= PyObject_GetAttrString(pObject,”printName”); //根据对象得到成员函数

PyEval_CallObject(pFunc,NULL);

Py_Finalize();

Return 0;

}

 

c++接收python返回的参数

def mix(a,b):

r1 = a + b

r2 = a – b

return (r1, r2)

 

#include<python.h>

int main()

{

Py_Initialize();

if(!Py_IsInitialized())

return 0;

PyObject *pModule = PyImport_ImportModule(“Demo”);

PyObject *pyFunc_mix = PyObject_GetAttrString(pModule,”mix”);

if(pModule && PyCallable_Check(pyFunc_mix))

{

PyObject *pyParams = PyTuple_New(2);

PyTuple_SetItem(pyParams,0,Py_BuildValue(“i”,5));

PyTuple_SetItem(pyParams,1,Py_BuildValue(“i”,2));

int r1 = 0, r2 = 0;

PyObject *pyValue = PyObject_CallObject(pyFunc_mix,pyParams); //调用函数返回结果

PyArg_ParseTuple(pyValue,”i|i”,&r1,&r2);//分析返回的元组值

if(pyValue)

{

printf(“%d   %d\n”,r1,r2);

}

}

Py_Finalize();

return 0;

}

做成了pdf版:点击此处下载

ps:附上敬爱的徒弟大人秋山的作业

徒弟大人的作业

 

 

 

 

 

 

“c++调用python方法总结”的207个回复

  1. My coder is trying to convince me to move to .net from PHP.
    I have always disliked the idea because of the expenses.
    But he’s tryiong none the less. I’ve been using WordPress on numerous websites for about a year
    and am anxious about switching to another platform. I have heard good things about
    blogengine.net. Is there a way I can import all my wordpress posts into it?
    Any kind of help would be really appreciated!

  2. Attractive section of content. I just stumbled upon your blog and in accession capital to assert that I acquire actually enjoyed account your blog posts.
    Anyway I will be subscribing to your feeds and even I achievement you access
    consistently fast.

发表评论

电子邮件地址不会被公开。 必填项已用*标注