C++扩展和嵌入Python.doc

上传人:wux****ua 文档编号:9020473 上传时间:2020-04-02 格式:DOC 页数:11 大小:47KB
返回 下载 相关 举报
C++扩展和嵌入Python.doc_第1页
第1页 / 共11页
C++扩展和嵌入Python.doc_第2页
第2页 / 共11页
C++扩展和嵌入Python.doc_第3页
第3页 / 共11页
点击查看更多>>
资源描述
C+ 扩展和嵌入 PythonPython简介Python是一种简单易学,功能强大的解释型编程语言,它有简洁明了的语法,高效率的高层数据结构,能够简单而有效地实现面向对象编程,特别适用于快速应用程序开发,也可以用来开发大规模的重要的商业应用。Python是一个理想的脚本语言。 Python免费开源,可移植到多种操作系统,只要避免使用依赖于特定操作系统的特性,Python程序无需修改就可以在各种平台上面运行。 Python拥有现代编程语言所具有的一切强大功能,Python标准库十分庞大,可以帮助开发者处理各种工作,如:图形用户界面、文件处理、多媒体、正则表达式、文档生成、单元测试、线程、数据库、网络通讯、网页浏览器、CGI、FTP、电子邮件、XML、HTML、WAV文件、密码系统、Tk和其他与系统有关的操作。只要安装了Python,这些功能都是可用的除了标准库以外,还有许多其他高质量的库,如wxPython、Twisted和 Python图形库等等数不胜数。 Python容易扩展和嵌入。Python提供的许多标准模块支持C或者C+接口。Python和C可以一起工作,它可以嵌入到C或者C+的应用程序当中,因此可用Python语言为应用程序提供脚本接口,由于支持跨语言开发,可用Python设计概念化应用程序,并逐步移植到C,使用前不必用 C重写应用程序。(Jython使Python可以和Java一起工作,使开发者可以在Python里面调Java的包,也可以在Java里面使用 Python的对象。还有更妙的,由于Jython的解释器完全用Java编写,因此可以在支持Java的任何平台上部署Python程序,甚至WEB浏览器也可以直接运行Python脚本。)提出问题在某个C+应用程序中,我们用一组插件来实现一些具有统一接口的功能,我们使用Python来代替动态链接库形式的插件,这样可以方便地根据需求的变化改写脚本代码,而不是必须重新编译链接二进制的动态链接库。Python强大的功能足以胜任,但是有一些操作系统特定的功能需要用C+来实现,再由Python调用。所以,最基础地,我们需要做到: 1. 把Python嵌入到C+应用程序中,在C+程序中调用Python函数和获得变量的值; 2. 用C+为Python编写扩展模块(动态链接库),在Python程序中调用C+开发的扩展功能函数。 常用的Python/C API介绍下面是例子中用到的几个Python/C API的简要介绍及示例代码。注意,这并不是这些函数的详细介绍,而仅仅是我们所用到的功能简介,更详细内容请参考文档1、2、3、4。打开Microsoft Visual Studio .NET 2003,新建一个控制台程序,#include ,并在main函数里加入示例代码。/先定义一些变量 char *cstr;PyObject *pstr, *pmod, *pdict;PyObject *pfunc, *pargs;1. void Py_Initialize( ) 初始化Python解释器,在C+程序中使用其它Python/C API之前,必须调用此函数,如果调用失败,将产生一个致命的错误。例:Py_Initialize();2. int PyRun_SimpleString( const char *command) 执行一段Python代码,就好象是在_main_ 函数里面执行一样。例:PyRun_SimpleString(from time import time,ctimenprint Today is,ctime(time()n);3. PyObject* PyImport_ImportModule( char *name) 导入一个Python模块,参数name可以是*.py文件的文件名。相当于Python内建函数_import_()。例:pmod = PyImport_ImportModule(mymod); /mymod.py4. PyObject* PyModule_GetDict( PyObject *module) 相当于Python模块对象的_dict_ 属性,得到模块名称空间下的字典对象。例:pdict = PyModule_GetDict(pmod);5. PyObject* PyRun_String( const char *str, int start, PyObject *globals, PyObject *locals) 执行一段Python代码。pstr = PyRun_String(message, Py_eval_input, pdict, pdict);6. int PyArg_Parse( PyObject *args, char *format, .) 解构Python数据为C的类型,这样C程序中才可以使用Python里的数据。例:/* convert to C and print it*/PyArg_Parse(pstr, s, &cstr);printf(%sn, cstr);7. PyObject* PyObject_GetAttrString( PyObject *o, char *attr_name) 返回模块对象o中的attr_name 属性或函数,相当于Python中表达式语句:o.attr_name。例:/* to call mymod.transform(mymod.message) */pfunc = PyObject_GetAttrString(pmod, transform);8. PyObject* Py_BuildValue( char *format, .) 构建一个参数列表,把C类型转换为Python对象,使Python可以使用C类型数据,例:cstr=this is hjss test, to uppercase;pargs = Py_BuildValue(s), cstr);9. PyEval_CallObject(PyObject* pfunc, PyObject* pargs) 此函数有两个参数,都指向Python对象指针,pfunc是要调用的Python 函数,通常可用PyObject_GetAttrString()获得;pargs是函数的参数列表,通常可用Py_BuildValue()构建。例:pstr = PyEval_CallObject(pfunc, pargs);PyArg_Parse(pstr, s, &cstr);printf(%sn, cstr);10. void Py_Finalize( ) 关闭Python解释器,释放解释器所占用的资源。例:Py_Finalize();Python2.4环境没有提供调试版本的Python24d.lib,所以上述示例在release模式下编译。编译完成后,把可行文件和附2给出的mymod.py文件放在一起,再点击即可运行。为了简化编程,附3 给出了simplepy.h。这样,调用mymod.transform变成如下形式:/#include”simplepy.h”CSimplepy py;py.ImportModule(mymod);std:string str=py.CallObject(transform, this is hjss test, to uppercase);printf(%sn, str.c_str();接下来,我们来用C+为Python编写扩展模块(动态链接库),并在Python程序中调用C+开发的扩展功能函数。生成一个取名为pyUtil的Win32 DLL工程,除了pyUtil.cpp文件以外,从工程中移除所有其它文件,并填入如下的代码: / pyUtil.cpp#ifdef PYUTIL_EXPORTS#define PYUTIL_API _declspec(dllexport)#else#define PYUTIL_API _declspec(dllimport)#endif#include#include#includeBOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ?) switch (ul_reason_for_call) case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; return TRUE;std:string Recognise_Img(const std:string url) /返回结果 return 从dll中返回的数据. : +url;static PyObject* Recognise(PyObject *self, PyObject *args) const char *url; std:string sts; if (!PyArg_ParseTuple(args, s, &url) return NULL; sts = Recognise_Img(url); return Py_BuildValue(s, sts.c_str() );static PyMethodDef AllMyMethods = Recognise, Recognise, METH_VARARGS,/暴露给Python的函数 NULL, NULL /* Sentinel */;extern C PYUTIL_API void initpyUtil() PyObject *m, *d; m = Py_InitModule(pyUtil, AllMyMethods); /初始化本模块,并暴露函数 d = PyModule_GetDict(m);在Python代码中调用这个动态链接库: import pyUtilresult = pyUtil.Recognise(input url of specific data)print the result is: + result用 C+为Python写扩展时,如果您愿意使用Boost.Python库的话,开发过程会变得更开心J,要编写一个与上述pyUtil同样功能的动态链接库,只需把文件内容替换为下面的代码。当然,编译需要boost_python.lib支持,运行需要boost_python.dll支持。 #include#include using namespace boost:python;#pragma comment(lib, boost_python.lib)std:string strtmp;char const* Recognise(const char* url) strtmp =从dll中返回的数据. : ; strtmp+=url; return strtmp.c_str();BOOST_PYTHON_MODULE(pyUtil) def(Recognise, Recognise);所有示例都在Microsoft Windows XP Professional + Microsoft Visual Studio .NET 2003 + Python2.4环境下测试通过,本文所用的Boost库为1.33版本。posted 2010-01-20 10:11 Marine Turtle 阅读(93) 评论(0) 编辑 用C语言扩展Python的功能 Pyton和C分别有着各自的优缺点,用Python开发程序速度快,可靠性高,并且有许多现成模块可供使用,但执行速度相对较慢;C语言则正好相反,其执行速度快,但开发效率低。为了充分利用两种语言各自的优点,比较好的做法是用Python开发整个软件框架,而用C语言实现其关键模块。本文介绍如何利用C语言来扩展Python的功能,并辅以具体的实例讲述如何编写Python的扩展模块。 一、简介 Python是一门功能强大的高级脚本语言,它的强大不仅表现在其自身的功能上,而且还表现在其良好的可扩展性上,正因如此,Python已经开始受到越来越多人的青睐,并且被屡屡成功地应用于各类大型软件系统的开发过程中。 与其它普通脚本语言有所不同,Python程序员可以借助Python语言提供的API,使用C或者C+来对Python进行功能性扩展,从而即可以利用Python方便灵活的语法和功能,又可以获得与C或者C+几乎相同的执行性能。执行速度慢是几乎所有脚本语言都具有的共性,也是倍受人们指责的一个重要因素,Python则通过与C语言的有机结合巧妙地解决了这一问题,从而使脚本语言的应用范围得到了很大扩展。 在用Python开发实际软件系统时,很多时候都需要使用C/C+来对Python进行扩展。最常见的情况是目前已经存在一个用C编写的库,需要在Python语言中使用该库的某些功能,此时就可以借助Python提供的扩展功能来实现。此外,由于Python从本质上讲还是一种脚本语言,某些功能用Python实现可能很难满足实际软件系统对执行效率的要求,此时也可以借助Python提供的扩展功能,将这些关键代码段用C或者C+实现,从而提供程序的执行性能。 本文主要介绍Python提供的C语言扩展接口,以及如何使用这些接口和C/C+语言来对Python进行功能性扩展,并辅以具体的实例讲述如何实现Python的功能扩展。 二、Python的C语言接口 Python是用C语言实现的一种脚本语言,本身具有优良的开放性和可扩展性,并提供了方便灵活的应用程序接口(API),从而使得C/C+程序员能够在各个级别上对Python解释器的功能进行扩展。在使用C/C+对Python进行功能扩展之前,必须首先掌握Python解释所提供的C语言接口。 2.1 Python对象(PyObject) Python是一门面向对象的脚本语言,所有的对象在Python解释器中都被表示成PyObject,PyObject结构包含Python对象的所有成员指针,并且对Python对象的类型信息和引用计数进行维护。在进行Python的扩展编程时,一旦要在C或者C+中对Python对象进行处理,就意味着要维护一个PyObject结构。 在Python的C语言扩展接口中,大部分函数都有一个或者多个参数为PyObject指针类型,并且返回值也大都为PyObject指针。 2.2 引用计数 为了简化内存管理,Python通过引用计数机制实现了自动的垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被引用了多少次。每当引用一次Python对象,相应的引用计数就增1,每当消毁一次Python对象,则相应的引用就减1,只有当引用计数为零时,才真正从内存中删除Python对象。 下面的例子说明了Python解释器如何利用引用计数来对Pyhon对象进行管理:例1:refcount.pyclass refcount: # etc.r1 = refcount() # 引用计数为1r2 = r1 # 引用计数为2del(r1) # 引用计数为1del(r2) # 引用计数为0,删除对象在C/C+中处理Python对象时,对引用计数进行正确的维护是一个关键问题,处理不好将很容易产生内存泄漏。Python的C语言接口提供了一些宏来对引用计数进行维护,最常见的是用Py_INCREF()来增加使Python对象的引用计数增1,用Py_DECREF()来使Python对象的引用计数减1。 2.3 数据类型 Python定义了六种数据类型:整型、浮点型、字符串、元组、列表和字典,在使用C语言对Python进行功能扩展时,首先要了解如何在C和Python的数据类型间进行转化。 2.3.1 整型、浮点型和字符串 在Python的C语言扩展中要用到整型、浮点型和字符串这三种数据类型时相对比较简单,只需要知道如何生成和维护它们就可以了。下面的例子给出了如何在C语言中使用Python的这三种数据类型:例2:typeifs.c/ build an integerPyObject* pInt = Py_BuildValue(i, 2003);assert(PyInt_Check(pInt);int i = PyInt_AsLong(pInt);Py_DECREF(pInt);/ build a floatPyObject* pFloat = Py_BuildValue(f, 3.14f);assert(PyFloat_Check(pFloat);float f = PyFloat_AsDouble(pFloat);Py_DECREF(pFloat);/ build a stringPyObject* pString = Py_BuildValue(s, Python);assert(PyString_Check(pString);int nLen = PyString_Size(pString);char* s = PyString_AsString(pString);Py_DECREF(pString);2.3.2 元组 Python语言中的元组是一个长度固定的数组,当Python解释器调用C语言扩展中的方法时,所有非关键字(non-keyword)参数都以元组方式进行传递。下面的例子示范了如何在C语言中使用Python的元组类型:例3:typetuple.c/ create the tuplePyObject* pTuple = PyTuple_New(3);assert(PyTuple_Check(pTuple);assert(PyTuple_Size(pTuple) = 3);/ set the itemPyTuple_SetItem(pTuple, 0, Py_BuildValue(i, 2003);PyTuple_SetItem(pTuple, 1, Py_BuildValue(f, 3.14f);PyTuple_SetItem(pTuple, 2, Py_BuildValue(s, Python);/ parse tuple itemsint i;float f;char *s;if (!PyArg_ParseTuple(pTuple, ifs, &i, &f, &s) PyErr_SetString(PyExc_TypeError, invalid parameter);/ cleanupPy_DECREF(pTuple);2.3.3 列表 Python语言中的列表是一个长度可变的数组,列表比元组更为灵活,使用列表可以对其存储的Python对象进行随机访问。下面的例子示范了如何在C语言中使用Python的列表类型:例4:typelist.c/ create the listPyObject* pList = PyList_New(3); / new referenceassert(PyList_Check(pList);/ set some initial valuesfor(int i = 0; i 3; +i) PyList_SetItem(pList, i, Py_BuildValue(i, i);/ insert an itemPyList_Insert(pList, 2, Py_BuildValue(s, inserted);/ append an itemPyList_Append(pList, Py_BuildValue(s, appended);/ sort the listPyList_Sort(pList);/ reverse the listPyList_Reverse(pList);/ fetch and manipulate a list slicePyObject* pSlice = PyList_GetSlice(pList, 2, 4); / new referencefor(int j = 0; j PyList_Size(pSlice); +j) PyObject *pValue = PyList_GetItem(pList, j); assert(pValue);Py_DECREF(pSlice);/ cleanupPy_DECREF(pList);2.3.4 字典 Python语言中的字典是一个根据关键字进行访问的数据类型。下面的例子示范了如何在C语言中使用Python的字典类型:例5:typedic.c/ create the dictionaryPyObject* pDict = PyDict_New(); / new referenceassert(PyDict_Check(pDict);/ add a few named valuesPyDict_SetItemString(pDict, first, Py_BuildValue(i, 2003);PyDict_SetItemString(pDict, second, Py_BuildValue(f, 3.14f);/ enumerate all named valuesPyObject* pKeys = PyDict_Keys(); / new referencefor(int i = 0; i PyList_Size(pKeys); +i) PyObject *pKey = PyList_GetItem(pKeys, i); PyObject *pValue = PyDict_GetItem(pDict, pKey); assert(pValue);Py_DECREF(pKeys);/ remove a named valuePyDict_DelItemString(pDict, second);/ cleanupPy_DECREF(pDict);三、Python的C语言扩展 3.1 模块封装 在了解了Python的C语言接口后,就可以利用Python解释器提供的这些接口来编写Python的C语言扩展,假设有如下一个C语言函数:例6:example.cint fact(int n) if (n import example example.fact(4)24四、结束语 作为一门功能强大的脚本语言,Python将被更加广泛地应用于各个领域。为了克服脚本语言执行速度慢的问题,Python提供了相应的C语言扩展接口,通过将影响执行性能的关键代码用C语言实现,可以很大程度上提高用Python编写的脚本在运行时的速度,从而满足实际需要。
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 图纸专区 > 大学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!