您好,欢迎访问三七文档
第8章Python扩展和嵌入由于Python是解释性的脚本语言,执行速度较慢。在某些需要提高脚本执行效率的情况下,可以考虑扩展Python,用C/C++来完成对效率要求高的部分。另外,由于Python功能强大,完全可以将其嵌入到C/C++中,以简化程序,减少代码。8.1扩展PythonPython提供了支持C/C++接口,可以方便地使用C/C++来扩展Python。用C/C++编写的Python扩展主要用于完成底层的系统操作,以及提高执行速度等。8.1.1扩展概述Python提供了接口API,通过使用API函数可以编写Python扩展。在Windows下可以使用VC来编译Python扩展。在UNIX和Linux下则可以使用gcc来编译。1.设置编程环境使用VC时需要设置一些头文件以及库文件的包含目录。如果使用VC++6.0,则设置过程如下所示。(1)单击【Tools】|【Options】命令,弹出如图8-1所示的对话框。(2)单击【Directories】标签,选择【Showdirectoriesfor】下拉列表框中的【Includefiles】项,将Python安装目录下的INCLUDE目录添加到【Directories】列表中,如图8-2所示。(3)选择【Showdirectoriesfor】下拉列表框中的【Libraryfiles】项,将Python安装目录下的LIBS目录添加到【Directories】列表中,如图8-3所示。(4)单击【OK】按钮完成操作。如果使用VisualStudio2005,则设置过程如下所示。(1)单击【工具】|【选项】命令,弹出如图8-4所示的对话框。(2)双击左侧列表树中的【项目和解决方案】项,选择【VC++目录】项,如图8-5所示。(3)选择【显示以下内容的目录】下拉列表框中的【包含文件】项,将Python安装目录下的include目录添加到列表中,如图8-6所示。图8-1Options对话框图8-2添加头文件图8-3添加库文件图8-4选项对话框图8-5设置VC++目录图8-6添加头文件(4)选择【显示以下内容的目录】下拉列表框中的【库文件】项,将Python安装目录下的libs目录添加到列表中,如图8-7所示。(5)单击【确定】按钮完成操作。图8-7添加库文件2.创建工程在VisualC++6.0中创建Python扩展过程如下所示。(1)单击【File】|【New】命令,弹出创建工程对话框。单击【Projects】标签,选择左侧列表中的【Win32Dynamic-LinkLibrary】项,在【Projectname】文本框中输入工程名“myext”,如图8-8所示。(2)单击【OK】按钮,弹出如图8-9所示的工程设置对话框。选中【AnemptyDLLproject.】单选框。图8-8创建工程对话框图8-9工程设置对话框(3)单击【Finish】按钮弹出如图8-10所示的确认对话框。单击【OK】按钮完成工程创建。(4)单击【File】|【New】命令弹出创建文件对话框,单击【Files】标签。选择左侧列表中的【C++SourceFile】项,在【File】文本框中输入文件名“myext.c”,如图8-11所示。图8-10确认对话框图8-11添加文件(5)单击【OK】按钮,在“myext.c”中添加如下内容。#include#includePyObject*show(PyObject*self,PyObject*args){char*message;constchar*title=NULL;HWNDhwnd=NULL;intr;if(!PyArg_ParseTuple(args,iss,&hwnd,&message,&title))returnNULL;r=MessageBox(hwnd,message,title,MB_OK);returnPy_BuildValue(i,r);}staticPyMethodDefmyextMethods[]={{show,show,METH_VARARGS,showamessagebox},{NULL,NULL}};PyMODINIT_FUNCinitmyext(){PyObject*mod;mod=Py_InitModule(myext,myextMethods);}(6)单击【Project】|【Settings】命令,弹出如图8-12所示的工程设置对话框。(7)选择【SettingsFor】下拉列表框中的【Win32Release】项。单击【Link】标签,将【Outpubfilename】文本框中的“Release/myext.dll”改为“Release/myext.pyd”,如图8-13所示。图8-12工程设置对话框图8-13设置Link选项(8)单击【C/C++】标签,选择【Category】下拉列表框中的【CodeGeneration】项,选择【Userun-timelibrary】下拉列表框中的【MultithreadedDLL】项,如图8-14所示。(9)单击【OK】按钮完成工程设置。(10)单击【Build】|【BatchBuild】命令,弹出如图8-15所示的对话框,将【myext-Win32Debug】单选框前的勾去掉。单击【Build】按钮生成Python扩展。图8-14设置C/C++选项图8-15编译工程编译完成后将在工程目录下的Release目录中生成“myext.pyd”文件,其为所编写的Python扩展。编写“usemyext.py”调用“myext.pyd”中的函数。代码如下所示。#-*-coding:utf-8-*-#file:usemyext.py#importmyext#导入myext模块printmyext.show(0,'ExtendPython','Python')#调用show函数脚本运行后如图8-16所示。由于Python官方的安装程序中不包含debug版的库文件,不能生成debug版的Python扩展,因此上述设置都是针对release版。如果需要生成debug版的Python扩展,则需要自己编译Python生成debug版的库文件。另外,使用VisualStudio2005编译Python扩展与上述过程类似,这里不再赘述。图8-16使用Python扩展8.1.2程序详解一般的Python扩展程序中应包含以下3部分内容。1.初始化函数初始化函数是必须的,用于Python解释器对模块进行正确的初始化。初始化函数的函数名必须以init开头,并加上模块的名字。例如上节中初始化函数的函数名为“initmyext”,其中“myext”为模块名。函数“initmyext”代码如下所示。PyMODINIT_FUNCinitmyext(){PyObject*mod;mod=Py_InitModule(myext,myextMethods);}其中PyMODINIT_FUNC为Python头文件中定义的宏,在Windows下其相当于_declspec(dllexport)void,即将initmyext声明为void型,并且将其设为DLL文件的导出函数。初始化函数中的Py_InitModule函数,其函数原型如下所示。PyObject*Py_InitModule(char*name,PyMethodDef*methods)其参数含义如下。•name:模块名。•methods:方法列表。2.方法列表方法列表中包含了Python扩展中的所有可以调用的函数方法。方法列表应该被声明为“staticPyMethodDef”。上一节实例中的方法列表如下所示。staticPyMethodDefmyextMethods[]={{show,show,METH_VARARGS,showamessagebox},{NULL,NULL}};每一个函数方法对应于方法列表中的由大括号包围的一项。大括号中由4部分组成,模块中的方法名,与之对应的Python扩展中的函数名、函数调用方法,以及方法描述。其中函数调用方法应该为“METH_VARARGS”或者“METH_VARARGS|METH_KEYWORDS”。也可以将函数调用方法设置为0。方法列表应该以由两个NULL组成的一项来表示结束。3.函数实现方法列表中包含了模块中方法对应的C语言函数实现。在Python扩展中所有的函数都应该被声明为“PyObject*”型,每个函数都应当含有两个“PyObject*”型的参数。在上一节的实例中,模块方法的实现函数如下所示。PyObject*show(PyObject*self,PyObject*args){char*message;constchar*title=NULL;HWNDhwnd=NULL;intr;if(!PyArg_ParseTuple(args,iss,&hwnd,&message,&title))returnNULL;r=MessageBox(hwnd,message,title,MB_OK);returnPy_BuildValue(i,r);}其中参数self只有在函数为Python的内置方法时才被使用,其余情况下self为一个空指针。参数args为在Python中向方法传递的参数。如果在方法列表中指定的函数调用方法为“METH_VARARGS”,则在函数中使用PyArg_ParseTuple处理参数。如果在方法列表中指定的函数调用方法为“METH_VARARGS|METH_KEYWORDS”,则应该使用PyArg_ParseTupleAndKeywords处理参数。其中PyArg_ParseTuple的函数原型如下所示。intPyArg_ParseTuple(PyObject*args,constchar*format,...)其参数含义如下。•args:传递的参数。•format:参数类型描述。PyArg_ParseTuple为可变参数函数,其后的参数即在函数中接受Python中传递参数的变量。在上述的show函数中,要使用3个参数,分别为hwnd、message、title。在PyArg_ParseTuple中将其作为参数,使用“&”向hwnd、message、title传递值,即将Python向show方法传递的参数依次赋值给hwnd、message、title。PyArg_ParseTuple函数中的format参数指定了其后参数的类型,在show函数中format参数为“iss”表示hwnd为整型,message和title为字符串。常见的指定参数类型的字符如表8-1所示。表8-1常见的指定参数类型的字符格式化字符C数据类型Python类型schar*字符串s#char*,int字符串及长度zchar*与s相同,但可以为NULL续表格式化字符C数据类型Python类型z#char*,int与s#相同,但可以为NULLiint长整型llongint长整型cchar单个字符的字符串ffloat双精度型ddouble双精度型8.1.3在Python扩展中使用MFC在Windows下使用MFC可以方便地进行GUI编程。MFC对基本的SDKAPI函数进行了封装,使用更为简便。在PythonWin中提供了部分MFC中的函数。在Python扩展中使用MFC与上一节中的例子有不同的地方。此处给出一个在Python扩展中使用MFC创建一个对话框的例子。整个过程如下所示。(1)单击【File】|【New】命令,弹出创建工程对话框。单击【Projects】标签,选择左侧列表中的【MFCAppWizard(dll)】项,在【Projectname】文本框中输入工程名“UseMFC”,如图8-17所示。(2)单击【OK】按钮,弹出如图8-18所示的工程设置对话框。选中【RegularDLLusingsharedMFCDLL】单选框,使用动态链接方式。该方式需要MFCDLL的支持,如果选中【RegularDLLwithMFCstat
本文标题:征服python
链接地址:https://www.777doc.com/doc-4890389 .html