Python是一种简单易学、功能强大的编程语言,它有高效率的高层数据结构,能简单而有效地实现面向对象编程。Python简洁的语法、对动态输入的支持和解释性语言的本质,使得它在很多领域的大多数平台上都是一个理想的脚本语言,特别适用于快速的应用程序开发。
C++继承了C语言的能力,能够使用指针直接操作内存,也可以嵌入汇编语言以获得最快的运行速度。它还支持面向对象、泛型编程等开发技术,可以在很高的层次上进行建模,以获得高度的抽象,几乎所有领域的软件都可以使用C++完成开发。
任何开发语言都不可能独当一面,包打天下,总有它独特的优缺点。但如果把不同的编程语言结合起来使用,却能发挥它的优点,弥补缺点,Boost Python库正是解决C++和Python混合编程的利器。
Boost Python库简要介绍
Boost Python库的设计目标是简化Python与C++语言的交互,可以方便地在Python和C++之间自由转换,充分利用了C++的高级特性和新技术,封装和屏蔽了很多底层实现,展现给应用层的是一个高度抽象、灵活和易于学习的接口。只要开发者会编写C++程序,就可以立刻使用Boost Python库为Python编写扩展程序,功能十分强大。此外Boost Python库全面支持C++和Python的各种特性,例如:C++到Python的异常转换、默认参数、关键字参数、引用和指针等,可以让C++与Python可以近乎完美地对接。
混合编程优势
基于Boost Python库可以构建出C++与Python的混合软件系统,它的优势:
l 使用Python的动态特性、解释能力和大量标准化模块,能够快速构建出可用的软件原型,利用C++改写其中运行效率低下的部分,作为底层模块供Python调用。这样既拥有Python的快速开发能力,又有了C++的运行高效。
l Boost Python库实现了两种功能丰富的优秀语言环境间的无缝协作,可以把软件系统的任何一个模块用这两种语言中的任意语言实现,系统中语言所占比例因需求变化而不同(侧重快速开发,使用Python;侧重运行效率,使用C++)。
对Boost Python库有了一个大致的概念后,为了帮助大家更快理解,本文将会通过一些运行实例,为大家演示如何通过利用Boost Python库来实现C++和Python语言的混合编程。
最简单的例子
分析代码:
注意:char const name是Python模块中使用的函数名称,可以与C++的函数名不一样,但要符合Python的语法规范。
通过上述步骤,就完成了C++为Python编写扩展模块的全部代码开发,如此轻松便为Python编写了扩展,是不是十分简单? 以下是Boost Python库能带来的便利:
l C++原有代码不用修改,为已存在的模块扩展到Python提供便利。
l C++和Python解耦,解决了跨语言相互依赖的问题。针对Python 2.X与3.X系列不兼容问题,只需要更换不同的编译库即可。
完成了上面示例中代码的开发,接下来编译dll,具体操作步骤如下:
1) 在VS2015中新建一个TestPython的Dll工程,导入上面的Test.h和Test.cpp文件,编译之后生成库文件(TestPython.dll)。
2) 将DLL拷贝到要使用的Python目录(新建的Python工作目录,可以是任意文件目录)下,或者在系统环境变量配置该DLL的引用目录。
3) Windows运行环境下需要把TestPython.dll修改成Test.pyd。
注意:pyd文件名必须和BOOST_PYTHON_MODULE中指定的模块名保持一致。
dll编译完成后,我们接着看编写的扩展程序是如何在Python中使用的。
分析代码:
1) 从Test包(模块)导入TestHello函数(代码3),导入的规则如下:
a) 从系统的目录中查找包名为Test的库,查找成功则返回,否则继续;
b) 从当前目录中查找包名为Test的库,查找成功则返回,否则报错。
2) 调用TestHello函数,并将返回的结果使用print打印出来,最终的执行结果如下:
至此,C++编写扩展模块及Python如何使用的示例已经全部完成了,十分简单,相信大家也对如何使用Boost Python库来实现C++与Python交互有了更近一步的理解。
1) 细心的人可能注意到了,上面的示例并不包含参数,而在实际的应用中可能包含不同类型的参数,这对实际应用的场景并不友好。。Python中有六个可以按数据是否允许可变进行划分的标准数据类型:
1) 不可变数据:Number(数字)、String(字符串)、Tuple(元组)、Sets(集合);
2) 可变数据:List(列表)、Dictionary(字典)。
那么如何在Python和C++之间进行参数传递呢?
参数传递
Python是使用C语言开发出来的,其本身就是一个C库,真正的Python在动态链接库里实现。所以C++中的一些数据类型在Python中是直接可以使用的,可以参考表1中数据:
C++ type
Python type
char
int
int/short/long(unsigned)
int
float
float
double
float
char *
str
bool
bool
表1
表1中列举了C++和Python通用的数据类型,对于如何使用,可能会有如下的几个问题:
1) 问题1通用数据类型如何传递?
2) 问题2可变数据类型(List/Dictionary)这种常用的容器类型如何传递?
3) 问题3参数传递方式有两种:值传递和引用传递,那么C++和Python交互的过程中,又是如何处理的?顺便介绍一下值传递和引用传递的概念:
a) 值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
b) 引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
带着上面的问题,我们通过一个例子来共同学习下Boost Python库对参数的处理机制。
参数传递的例子
分析代码:
1) TestInt函数展示了Python和C++通用数据类型的使用范例(代码4-10),表1中列举的范例都可以使用此种方式传递参数,有兴趣的可以尝试一下。
2) TestContainer函数展示了如何针对Python中的容器对象,使用Boost Python库实现C++和Python参数传递的范例(代码12-46)。容器内容的读取使用模块类extract,主要的功能是实现Python对象到C++具体数据类型的转换,关于extract的定义如下:
通过上面的例子,我们对Boost Python库的工作原理有了大致了解:
1) 扩展与Python容器对象兼容的数据类型
2) 提供读写容器数据的API方法
3) 兼容Python容器的一些常用操作
总之,Boost Python完全封装Python C API提供的接口,向开发者提供高度抽象、灵活和易于学习的接口。
问题1、2已经有了答案,关于问题3我们需要通过Python代码以及运行结果,解析运行机制才能找到答案。
Python测试代码:
执行结果:
结果解析,我们可以得出如下结论:
1) 不可变数据类型(Number/String/Tuple/Sets)采用的是值传递
2) 可变数据类型(List/Dictionary)采用的是引用传递
以上就是利用Boost Python库实现C++和Python的交互及参数传递相关问题的介绍,希望能给大家的工作带来帮助,下一篇我们将介绍C++回调Python的技术手段,敬请关注!