用户登录  |  用户注册
加入收藏设为首页会员中心我要投稿爽死小游戏平坦软件商城论坛RSS
当前位置:首页 > 教程资料 > 程序开发 > C/C++
日期:2010-08-24 07:34:50  来源:网络收集

C++调用Python函数

     Python代码在实现某些功能的时候非常方便,如果能够将Python代码与C++程序结合起来,那么一定会使Problem Solving方便许多(比如,游戏脚本系统)~jmj平坦软件园

    从学完Python开始就一直想研究一下C++内嵌Python是怎么回事,可是每次都坚持不下来。。。今天上校内,偶然间看到同学求助,怎么实现输入表达式输出结果~我想到了Python的builtin函数eval,正好借这个机会研究一下怎么实现C++调用Python函数!jmj平坦软件园

    假定您的系统中已经安装了Python,我使用的版本是2.6~jmj平坦软件园

    1.配置IDE。jmj平坦软件园

    我用的是VS2008,只需要将Python安装路径下的include文件夹和libs文件夹添加到C++目录中即可。步骤是:Tools -> Options -> Project & Solution -> VC++ Dir选择右上的Dropdown List,分别将include文件夹和libs文件夹添加到include和lib项中。jmj平坦软件园

    2.编写Python脚本。jmj平坦软件园

    为了完成自动计算值的功能,我写了如下的脚本(文件名是python_code.py):jmj平坦软件园

 jmj平坦软件园

    将这个文件与C++程序文件放到同一目录下,这样保证编译器可以根据相对路径找到。jmj平坦软件园

    3.Python嵌入的方式 - 高级vs低级jmj平坦软件园

    接下来进入C++内嵌Python函数的关键部分了。根据官方的帮助文档,有两个类型的Python调用,High Level与Low Level。High Level就是调用者不需要管理与Python相关的内存,只有3行代码即可,分别是Py_Initialize()来初始化解释器(注意,此时程序仍然是由C++的编译器进行编译),调用PyRun_SimpleString()其中参数是要执行的Python代码,如果是一个确定的Python文件,那么我们可以调用PyRun_SimpleFile()直接执行Python文件。最后调用Py_Finalize()方法结束解释器工作。jmj平坦软件园

    使用High Level对程序员的要求非常少,基本就是会写Python代码就会在C++中调用Python的方法,但是弊端就是当前程序不能与Python的方法进行数据的交互,所以局限性非常大。jmj平坦软件园

    所以,如果我们需要与Python程序进行交互,比如计算表达式的值,我们只能使用低级的方法了。jmj平坦软件园

    4.Low Level程序编写步骤。jmj平坦软件园

    说实话,以前几次当我想学习Python内嵌的时候都是因为看到为了进行Low Level调用而编写的冗长的C++代码,实在是太恐怖了。。可是今天静下来看一看其实只有4步:jmj平坦软件园

    (1)导入要用到的模块:jmj平坦软件园

     要导入模块其实很简单,首先我们需要提供模块的文件名,注意,跟Python中导入模块一样,这里的文件名不能包含".py"后缀,比如我的文件名是python_code.py,我在程序中只需要提供"python_code"这个字符串就可以了。这一部分代码如下(注意使用到的两个函数:PyString_FromString和PyImport_Import):jmj平坦软件园

 jmj平坦软件园

    注意,在C++中一切Python的object都是用PyObject*来代替。第一行语句将C++中的char数组转化为Python中的字符串,然后利用这个文件名导入模块!请注意函数是PyImport_Import,而不是别的。jmj平坦软件园

    好了,模块导入之后我们需要验证模块导入是否成功,如果成功我们就可以进行第二步了,找到我们要调用的方法。jmj平坦软件园

    (2)找到要调用的方法。jmj平坦软件园

    基本原理是这样的,在C++中,如果我们有了模块,就可以获得模块对应的attr列表(dir(模块名)),然后我们就可以利用我们所需要的方法名找到我们所需要的那个attr。找到之后我们要判断时候找到成功,而且是否是可以调用的(callable)。这部分代码如下:jmj平坦软件园

 jmj平坦软件园

    第一句话首先利用PyObject_GetAttrString找到我们所需的“方法”对象,然后检测对象时候有效,是否是Callable的,如果这两者检测都成功了,那么ok,进入下一步。jmj平坦软件园

    (3)构造参数。jmj平坦软件园

   方法有了,接下来就缺参数了。参数是以tuple的形式传递给方法的,所以我们需要一个PyObject*对象来充当一个Tuple,利用PyTuple_New方法即可。这个方法的参数是tuple内元素的个数,我认为可以理解为参数的个数。由于我的Python代码只有一个参数,所以这里我直接给1,其他情况可以根据参数的数量赋值。jmj平坦软件园

    然后解释构建参数了,根据参数的不用类型,可以调用不同的方法。这里由于我在C++程序中的参数是字符串,在Python中的参数也是一个字符串,所以我使用PyString_FromString方法,其中Py是前缀,第一个String指的是在Python代码中我们需要一个String,也就是目的参数类型,而FromString顾名思义,就是C++中参数的类型。这个方法接受一个参数,也就是一个string,注意,这个string其实是char型数组。返回的结果是一个PyObject*。jmj平坦软件园

    最后一步是要把构造的参数赋值给我们的Tuple,用PyTuple_SetItem方法就可以了。第一个参数是指向Tuple的PyObject指针,第二个参数是value在Tuple中的位置参数,从0开始,最后一个就是咱们的value了,这部分代码如下:jmj平坦软件园

 jmj平坦软件园

    (4)调用方法,取返回值。jmj平坦软件园

    好了,大功即将告成~最后一步当然是调用方法了!利用PyObject_CallObject方法,第一个参数是指向函数的那个PyObject指针,第二个参数则是指向我们Tuple的那个PyObject指针。返回值仍然是PyObject指针对象。我们需要对它进行解析,将它转换成C++的类型。这部分代码如下:jmj平坦软件园

 jmj平坦软件园

     好了,到这里调用的全部过程就完成了,其实还不赖。最后,为了方便大家理解,我把整个代码贴了上来。jmj平坦软件园

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!jmj平坦软件园

    特别说明,如果您是用Python安装包的形式安装的Python,那么这个程序只能以Release方式运行!原因是安装包版Python在libs文件夹下只有Release版的lib文件,而debug模式需要Python26_d.lib,也就是debug模式的。如果您在运行时提示无法打开python26_d.lib文件,那么请换成Release模式,或者下载Python源码自己编译,这样就会生成_d的lib文件了!jmj平坦软件园

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!jmj平坦软件园

    由于我的水平实在有限,文中难免有错误,希望各位看到之后留言指正!谢谢各位!jmj平坦软件园

 jmj平坦软件园

[]

收藏: 我要收藏

作者:spvm1313113
阅读统计:[] [返回页首] [打 印]

文章评论共有条评论 评论内容只代表网友观点,与本站立场无关!

评论人 评论内容

评论时间

用户名: 密码:
验证码: 匿名发表
Copyright © 2009-2010 FLATWS.CN. All Rights Reserved .