使用C++扩展Python的功能 转自:http://blog.csdn.net/magictong/article/details/8897568#comments

使用C++扩展Python的功能

环境

VS2005Python2.5.4 Windows7(32位)

简介

长话短说,这里说的扩展Python功能与直接用其它语言写一个动态链接库,然后让Python来调用有点不一样(虽然本质是一样的)。而是指使用Python本身提供的API,使用C++来对Python进行功能性扩展,可以这样理解,使用更高效的语言实现一些算法计算等等需要更高执行效率的核心(或者需要与系统进行密切交互的)模块,然后让Python像调用内建标准库的方式来调用这些模块,听起来是不是很诱人?!在软件技术高速发展的今天,借助几种计算机语言来实现一个系统的例子数不胜数,目的不外乎就是性能和便利的平衡。譬如本文要讨论的使用C++来扩展Python就是Python和C++的一种巧妙的有机结合,好处不言而喻,既可以获得和C++相似的执行性能,又可以利用Python的开发灵活性。由于Python本身是使用C实现的,二者结合起来还是比较容易的。

基本流程

本文不适合这样的读者——对Python完全不了解或者对C\C++完全不了解,道理你们懂的。另外就是Python里面有6种基本数据类型。你需要了解如何在C和Python之间对这些类型进行转化(这不在本文讨论范围,可以参考[1])。

言归正传,感觉前面说得太多了,实际上很简单,因此我决定少说多做。一个C++的Python扩展模块至少应该有导出函数方法列表初始化函数三个部分。我们用VS2005这个强大的工具开工!一般来说,你应该建一个Dll工程(至于使用exe来扩展Python可以不可以,暂时还没研究过)。下面按部就班的说明(关键说明在注释部分)。

一、初始化函数

//-------------------------------------------------------------------------

// 函数        : initPyExt

// 功能        : 初始化函数

// 返回值     :PyMODINIT_FUNC

// 附注        : 注意,这个函数的名字不能改动。必须是init+模块名字,

// 我们的模块名字是PyExt,所以函数名是initPyExt。Python在导入

// 我们的PyExt模块时,会找到这个函数,并调用。这个函数实现的

// 功能很简单,通过调用Py_InitModule将模块名字和映射表结合起

// 来,它的意思是说PyExt这个模块使用PyExtMethods这个映射表。

//-------------------------------------------------------------------------

PyMODINIT_FUNCinitPyExt()

{

Py_InitModule("PyExt",PyExtMethods);

}

二、方法列表

/*

方法列表,这个是一个C结构数组。把需要扩展的函数都映射到这个表里。

那么Python就知道你的这个扩展模块支持一些什么方法了。表的第一个字

段是方法名字,也是通过Python来调用时的名字。第二个字段是导出函数,

是真正调用的函数,也是C\C++实现的函数。第三个参数是指明Python向

C\C++函数传递参数的形式。可选的两种方式是METH_VARARGS和

METH_KEYWORDS,其中METH_VARARGS是参数传递的标准形式,它通

过Python的元组在Python解释器和C函数之间传递参数,若采用

METH_KEYWORD方式,则Python解释器和C函数之间将通过Python的字典

类型在两者之间进行参数传递。第四个字段是这个函数的说明。如果你在

python里来help这个函数,将显示这个说明。相当于在python里的函数的文档说明。

*/

staticPyMethodDefPyExtMethods[]=

{

{"Add", Add,METH_VARARGS,"Addtwo number - edit by magictong."},

{"ExecSystem",ExecSystem,METH_VARARGS,"Execute a shell command - edit bymagictong." },

{NULL,NULL, 0,NULL}

};

三、导出函数

//-------------------------------------------------------------------------

// 函数        : Add

// 功能        : 这是一个加法函数

// 返回值     :PyObject*

// 参数        : PyObject*self 这个参数我们暂时不用理会

// 参数        : PyObject*args 是一个参数列表,我们需要从它解析出参数

// 附注        :

// 所有的导出函数都具有相同的原型:

// PyObject*method(PyObject* self, PyObject* args);

//PyArg_ParseTuple来完成解析参数任务。它的第一个参数是args,

// 就是我们要转换的参数。第二个是格式符号。"s"代表是个string。

// 从args里提取一个参数就写"s",两个的话就写"s|s",如果是一个

// string,一个int,就写"s|i",有点和printf类似哦。第三个参数就是

// 提取出来的参数放置的真正位置。必须传递这个参数的地址。

//-------------------------------------------------------------------------

staticPyObject*Add(PyObject*self,PyObject*args)

{

intx = 0 ;

inty = 0;

intz = 0;

if(!PyArg_ParseTuple(args,"i|i", &x, &y))

returnNULL;

z=x +y;

returnPy_BuildValue("i",z);

/*

调用完之后我们需要返回结果。这个结果是c的type或者是我们自己定义的类型。

必须把他转换成PyObject,让python认识。这个用Py_BuildValue来完成。他

是PyArg_ParseTuple的逆过程。他的第一个参数和PyArg_ParseTuple的第二个

参数一样,是个格式化符号。第三个参数是我们需要转换的参数。Py_BuildValue

会把所有的返回只组装成一个tutple给python。

如果对应的C函数没有返回值(即返回值类型为void),则应返回一个全局的None

对象(Py_None),并将其引用计数增,如下所示:

Py_INCREF(Py_None);

returnPy_None;

*/

}

四、再加点功能

intcmd(constchar* arg)

{

returnsystem(arg);

}

staticPyObject*ExecSystem(PyObject*self,PyObject*args)

{

constchar*command;

if(!PyArg_ParseTuple(args,"s", &command))

returnNULL;

intn =cmd(command);

returnPy_BuildValue("i",n);

}

编译

开编,编译出来的PyExt.dll文件改名为PyExt.pyd放入Python的C:\Python25\DLLs目录就可以全局使用了,如果你只想某个Python的工程,放在工程的相对路径下面就可以了。

使用

可能的问题

里面的这些PyMODINIT_FUNC,与Python相关的宏和定义在哪里呢?定义下#include<Python.h>就可以了,但是定义了之后提示Python.h找不到还是编译不过怎么办?这说明你没有安装Python或者安装了但是没有把头文件路径引入Path环境变量,或者你把Python的include目录加入工程的附加包含目录(Additional IncludeDirectories),一般是C:\Python25\include这个目录,其中C:\Python25是Python的安装目录,按你机器的实际情况配置)。

如果提示:Error  1    fatal error LNK1104:cannot open file ‘python25_d.lib‘      类似这样的错误,一般可能是没有安装Python的开发版本,没关系,你使用Release编译一下,如果还不行,就把C:\Python25\libs目录加入工程的附加库目录(Additional LibraryDirectories)。

参考文献

[1] python官网http://www.python.org/

[2] 用C语言扩展python的功能https://www.ibm.com/developerworks/cn/linux/l-pythc/

[3] C++扩展和嵌入Pythonhttp://www.vckbase.com/index.php/wv/1258

[4] Python调用C/C++模块http://blog.csdn.net/masefee/article/details/4750920

时间: 2024-10-11 07:00:14

使用C++扩展Python的功能 转自:http://blog.csdn.net/magictong/article/details/8897568#comments的相关文章

如何简单实现接口自动化测试(基于 python) 原博主地址https://blog.csdn.net/gitchat/article/details/77849725

如何简单实现接口自动化测试(基于 python) 2017年09月05日 11:52:25 阅读数:9904 GitChat 作者:饿了么技术社区 原文:如何简单实现接口自动化测试(基于 python) 关注微信公众号:GitChat 技术杂谈 ,这里一本正经的讲技术 一.简介 本文从一个简单的登录接口测试入手,一步步调整优化接口调用姿势,然后简单讨论了一下接口测试框架的要点,最后介绍了一下我们目前正在使用的接口测试框架pithy.期望读者可以通过本文对接口自动化测试有一个大致的了解. 二.引言

python特殊属性和方法的运用 -转自http://blog.csdn.net/business122/article/details/7568446

用__dict__把dict转换为对象的属性 1 class Messenger: 2 def __init__(self, **kwargs): 3 self.__dict__ = kwargs 4 5 6 m = Messenger(info="some information", b=[’a’, ’list’]) 7 m.more = 11 8 print m.info, m.b, m.more  以下为转载: Python 用下划线作为变量前缀和后缀指定特殊变量 _xxx 不能

linux上Kettle定时执行(转换的单步执行,job的单步执行,环境变量,kettle定时功能,效率问题等)转自(http://blog.csdn.net/feng19821209/article/details/5800960)

1,Kettle跨平台使用.    例如:在AIX下(AIX是IBM商用UNIX操作系统,此处在LINUX/UNIX同样适用),运行Kettle的相关步骤如下:    1)进入到Kettle部署的路径    2)执行 chmod *.sh,将所有shell文件添加可执行权限    3)在Kettle路径下,如果要执行transformation,就运行./pan.sh -file=?.ktr -debug=debug -log=log.log    其中.-file说明你要运行的transfor

【转】用C语言扩展Python的功能

原作者:肖文鹏 ([email protected]),原文地址:http://www.ibm.com/developerworks/cn/linux/l-pythc/ Pyton和C分别有着各自的优缺点,用Python开发程序速度快,可靠性高,并且有许多现成模块可供使用,但执行速度相对较慢:C语言则正好相反,其执行速度快,但开发效率低.为了充分利用两种语言各自的优点,比较好的做法是用Python开发整个软件框架,而用C语言实现其关键模块.本文介绍如何利用C语言来扩展Python的功能,并辅以具

转:用C语言扩展Python的功能

转自:http://www.ibm.com/developerworks/cn/linux/l-pythc/ 一.简介 Python是一门功能强大的高级脚本语言,它的强大不仅表现在其自身的功能上,而且还表现在其良好的可扩展性上,正因如此,Python已经开始受到越来越多人的青睐,并且被屡屡成功地应用于各类大型软件系统的开发过程中. 与其它普通脚本语言有所不同,Python程序员可以借助Python语言提供的API,使用C或者C++来对Python进行功能性扩展,从而即可以利用Python方便灵活

Python的功能模块[1] -&gt; struct -&gt; struct 在网络编程中的使用

struct模块 / struct Module 在网络编程中,利用 socket 进行通信时,常常会用到 struct 模块,在网络通信中,大多数传递的数据以二进制流(binary data)存在.传递字符串时无需过多担心,但传递 int,char 之类的基本数据时,就需要一种机制将某些特定的结构体类型打包成二进制流的字符串,然后在进行网络传输,而接收端也可以通过某种机制进行解包还原出原始数据.struct 模块便提供了这种机制,该模块主要作用就是对 python 基本类型值与用 python

Python的功能模块[2] -&gt; abc -&gt; 利用 abc 建立抽象基类

abc模块 / abc Module 在定义抽象方法时,为了在初始化阶段就检测是否对抽象方法进行了重定义,Python 提供了 abc 模块. 1 from abc import ABCMeta, abstractmethod 2 3 # Generate a abstract base obj - MyABC 4 class MyABC(metaclass=ABCMeta): 5 #__metaclass__ = ABCMeta 6 @abstractmethod 7 def run(self

关于Python常见功能使用的博客收藏

Python绘制曲面和曲面对应的等高线图: https://blog.csdn.net/weixin_40198632/article/details/78570679 python实现三维拟合 https://blog.csdn.net/changye777/article/details/78437491 原文地址:https://www.cnblogs.com/dowtowne/p/10289881.html

利用boost.python 通过c++语言来扩展python (python.boost)

python语言的优良性就不多说了,我想提下如何使用boost.python,通过boost.python既可以将python转移到C++上,通过Python库,也可以通过C++来扩展python,下面主要介绍使用boost.python来扩展python的功能,第一次用boost.python,倒腾了半天才搞定: 首先列出我的测试环境: 我用的是VS2010,python2.7,我用VS2010创建了一个windows DLL的项目,项目名称为pylib,在DLL main中加入如下代码: /