python利用写模块_使用C++编写python扩展模块

简介

长话短说,这里说的扩展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或者安装了但是没有把头文件路径引入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)。

参考文献

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437149.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【编译原理】词法分析程序设计

概述 词法分析即对程序源码进行分词处理,分词处理就是把文本流分割成一个又一个符号。分词处理的输入输出是什么呢? 输入是源码字符串流输出是: 整型的类型枚举值,表示符号类型,如字符串;符号内容信息&…

【转】3.6(译)构建Async同步基元,Part 6 AsyncLock

传送门:异步编程系列目录…… 最近在学习.NET4.5关于“并行任务”的使用。“并行任务”有自己的同步机制,没有显示给出类似如旧版本的:事件等待句柄、信号量、lock、ReaderWriterLock……等同步基元对象,但我们可以沿溪这一编程习…

python 当前时间减一个月_python排序了解一下

排序是每个开发人员都需要掌握的技能。排序是对程序本身有一个全面的理解。不同的排序算法很好地展示了算法设计上如何强烈的影响程序的复杂度、运行速度和效率。今天的文章和谈谈大家都熟悉的各种排序使用 Python 如何实现,废话就不多说啦,开干&#xf…

开发与重构

软件开发过程主要追求的是高效、易于维护。 高效开发体现了代码的复用率即开发效率,是为了缩短开发周期。 易于维护体现了代码的重构效率,是为了缩短维护周期。 编程语言,从C到C,实现了从函数复用,到类复用。其实编程…

【转】3.7(译)构建Async同步基元,Part 7 AsyncReaderWriterLock

传送门:异步编程系列目录…… 最近在学习.NET4.5关于“并行任务”的使用。“并行任务”有自己的同步机制,没有显示给出类似如旧版本的:事件等待句柄、信号量、lock、ReaderWriterLock……等同步基元对象,但我们可以沿溪这一编程习…

面向对象软件开发代码结构(1)

类内部结构 类内部架构实际上是一个小型的状态机,成员变量是状态变量,成员函数是处理机。一般提倡一个类实现一种特定的功能,这样可以降低实现的复杂性,状态机越简单,越利于实现。 实例间通信 软件的功能是多个模块…

python猜数字1001untitled_ML - Python 基础

数据类型 Numeric & String1. Python数据类型1.1 总体:numerics, sequences, mappings, classes, instances, and exceptions1.2 Numeric Types: int (包含boolean), float, complex1.3 int: unlimited length; float: 实现用double in C, 可查看 sys.float_inf…

【转】4.1触碰jQuery:AJAX异步详解

传送门:异步编程系列目录…… 示例源码:触碰jQuery:AJAX异步详解.rar AJAX 全称 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。它并非一种新的技术,而是以下几种原有技术的结合体。 1) 使…

QStackedWidget实现自适应紧凑布局

前言 本文提出了一种使QStackedWidget尺寸根据内容自适应调整的解决方法。 问题提出 我们知道,QStackedWidget可以包含多个可切换的子窗口。多个子窗口的高度不一样时,此时将QStackedWidget放在一个垂直布局中,所有子窗口会保持和最高的子…

linux查看tcl版本_查看Linux内核版本的方法有几个?你也是这样操作吗?

请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习1. 前言内核是操作系统的核心组件。 它管理系统的资源,是计算机硬件和软件之间的桥梁。您可能因多种原因需要确切知道GNU / …

【转】4.2使用jQuery.form插件,实现完美的表单异步提交

传送门:异步编程系列目录…… 示例下载:使用jQuery.form插件,实现完美的表单异步提交.rar 抓住6月份的尾巴,今天的主题是 今天我想介绍的是一款jQuery的插件:Jquery.form.js 官网。 通过该插件,我们可以非常…

python医学数据挖掘_GitHub - SSSzhangSSS/Python-Data-mining-Tutorial: Python数据挖掘教程

Python数据挖掘教程作者 : 长行说明 : 本教程以9周的数据挖掘教程为主,每周包括5天的知识学习和2天的案例实现。以周为阶段,每周包括5天的知识内容(Day)、1天的案例实现(Example)和1天的小测验(Test);此外还可能包含选学部分(Extra)。案例的难…

面向对象软件开发代码结构(2)

使用封装降低信息的复杂度 封装是面向对象编程的核心思想之一。 封装的过程,是将大量的信息(过程、数据),凝缩成满足特定需求的接口的过程。 从数量上来说,好的封装必然是将大量的、与业务交互无关的实现细节隐藏起来…

什么方式可以通过影子系统传播恶意代码_将恶意代码隐藏在图像中:揭秘恶意软件使用的隐写术...

概述本周,许多Facebook用户都会发现,一些用户发布图片上出现了原本应该隐藏的图像标签。由此可以证明,图像可以携带大量表面上不可见的数据。实际上,Facebook和Instagram所使用的图片元数据与恶意攻击者制作的特制图像相比显得非常…

一种类的渐进式开发写法

// 主类,一般为窗口类 class MainClass { public:FuncClass1 *a;FuncClass2 *b; }// 实现某个功能的类 class FuncClass1 { public:FuncClass1(MainClass *) }// 实现某个功能的类 class FuncClass2 { public:FuncClass2(MainClass *) }每加一个大的功能&#xff0c…

【转】SQL中where, group by, having的用法和区别

group by,where,having 是数据库查询中最常用的几个关键字。在工作中,时常用到,那么,当一个查询中使用了where ,group by ,having及聚集函数时 ,执行顺序是怎么样的?为了回答这个问题,将这个三个关键字的用…

无法嵌入互操作类型 请改用适用的接口_西门子COMOS软件开发定制学习7-嵌入谷歌浏览器内核...

首先需要声明的是,本篇并非COMOS实用案例,只是希望借此让大家了解,如何使用微软的WPF和C#语言开发COMOS插件。首先看下效果图功能说明:拖拽COMOS设备至定制的浏览器,自动根据设备的名称和其制造商参数值,搜…

Win10上VMware的问题汇总

装xp很卡顿的问题 卸载360,重启电脑即可。 拖拽文件/文件夹到虚拟机直接卡住 使用15.1版本的VMware即可。 资源: 链接:https://pan.baidu.com/s/1dtr_cPwzprRTznpxj-OKTw 提取码:1wpj

【转】C#与C++的发展历程第一 - 由C#3.0起

C#5.0作为第五个C#的重要版本,将异步编程的易用度推向一个新的高峰。通过新增的async和await关键字,几乎可以使用同编写同步代码一样的方式来编写异步代码。 本文将重点介绍下新版C#的异步特性以及部分其他方面的改进。同时也将介绍WinRT程序一些异步编…

python数据库实例_Python操作MySQL数据库9个实用实例

用python连接mysql的时候,需要用的安装版本,源码版本容易有错误提示。下边是打包了32与64版本。MySQL-python-1.2.3.win32-py2.7.exeMySQL-python-1.2.3.win-amd64-py2.7.exe实例 1、取得 MYSQL 的版本实例 2、创建一个表并且插入数据实例 3、 python 使…