【Python】python扩展
当python的基本功能无法满足要求。或者是为了保密源码(.py)、遇到性能瓶颈时,我们经常要扩展python,扩展语言能够是C/C++、Java、C#等。
为python创建扩展须要三个基本的步骤:创建应用程序代码;利用样板来包装代码;编译与測试。
1、 创建应用程序代码
我们创建一个C代码PythonEx.c,实现两个函数fac()和reverse(),分别用来求阶乘和逆转字符串,test()函数是用来測试fac()和reverse()基本功能的。以防问题带入python。
// PythonEx.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int fac(int n)
{
if (n < 2) {
return (1);
}
else {
return (n) * fac(n - 1);
}
}
char* reverse(char *s)
{
register char t;
register char *p = s;
register char *q = (s + strlen(s) -1);
while (p < q) {
t = *p;
*p++ = *q;
*q-- = t;
}
return s;
}
int test()
{
char s[BUFSIZ];
printf("3! = %d\n", fac(3));
printf("6! = %d\n", fac(6));
printf("9! = %d\n", fac(9));
strcpy(s, "abcdefg");
printf("'abcdefg' after reversing is '%s'\n", reverse(s));
strcpy(s, "python");
printf("'python' after reversing is '%s'\n", reverse(s));
return 0;
}
2、 用样板包装代码
样板是扩展代码与python解释器之间进行交互的桥梁,主要分为以下4步。
a.包括python的头文件。
找到python头文件位置并确保编译器的訪问权限,然后在代码中inlcude这个头文件,例如以下:
#include “Python.h”
b.为每个模块的每个函数添加一个型如PyObject* Module_func()的包装函数。
这部分须要为全部想被python环境訪问的函数都添加一个静态的函数。函数的返回值类型为PyObject*,函数名前面要加上模块名和一个下划线。
包装函数的用处就是先把python的值传递给C,然后调用我们想要调用的相关函数。当这个函数完毕要返回python的时候,把函数的计算结果转换成python的对象,然后返回给python。那么。在从python到C的转换就用PyArg_Parse*系列函数,在从C转到python的时候,就用Py_BuildValue()函数。
以下我们包装fac()和reverse()函数,如果其模块名为CustomPy,例如以下:
static PyObject* CustomPy_fac(PyObject *self, PyObject *args)
{
int num;
if (!PyArg_ParseTuple(args, "i", &num)) { // i i.e. int->int
return NULL;
}
return (PyObject*)Py_BuildValue("i", fac(num)); // i i.e. int->int
}
static PyObject* CustomPy_reverse(PyObject *self, PyObject *args)
{
char *orig_str; // original
char *dup_str; // reversed
PyObject *retval;
if (!PyArg_ParseTuple(args, "s", &orig_str)) { // s i.e. str->char*
return NULL;
}
retval = (PyObject*)Py_BuildValue(
"ss", // s i.e. char*->str
orig_str,
dup_str = reverse(strdup(orig_str))); // strdup
free(dup_str); // free after strdup
return retval; // return tuple(orig_str, dup_str)
}
static PyObject* CustomPy_test(PyObject *self, PyObject *args)
{
test();
return (PyObject*)Py_BuildValue("");
}
以下是Python和C/C++之间的数据格式——
FormatCode
Python
Type C/C++
Type
s
str char*
z
str/None char*/NULL
i
int int
l
long long
c
str char
d
float double
D
complex Py_Complex*
o
(any) PyObject*
S
str PyStringObject
c.为每个模块添加一个型如PyMethodDef ModuleMethods[]的数组。
static PyMethodDef CustomPyMethods[] = {
{"fac", CustomPy_fac, METH_VARARGS},
{"reverse", CustomPy_reverse, METH_VARARGS},
{"test", CustomPy_test, METH_VARARGS},
{NULL, NULL},
};
完毕包装函数后。把他们添加到一个数组中,以便于python解释器能够导入并调用它们。
每个数组都包括了函数在python中的名字、对应的包装函数的名字以及一个METH_VARARGS常量,这个常量表示參数以tuple形式传入。最后是一个NULL数组表示列表结束。
d.添加模块初始化函数void initModule()
void initCustomPy()
{
Py_InitModule("CustomPy", CustomPyMethods);
}
这部分代码在模块被导入的时候被解释器调用。
另外。创建扩展还能够先写包装代码,使用桩函数、測试函数或哑函数,在开发过程中慢慢地把这些函数用有实际功能的函数替换。
3、编译与測试
为了让新python扩展能被创建。须要把它们与python库放在一起编译,曾经可能要用到Makefile,如今使用distutils模块就能够了,能够方便地编译、安装和分发这些模块、扩展和包。仅仅需创建一个setup.py脚本即可。
#!/usr/bin/env python
from distutils.core import setup, Extension
MOD = 'CustomPy'
setup(name = MOD, ext_modules = [Extension(MOD, sources = [PythonEx.c])])
以下直接执行setup.py脚本来创建自己定义模块。或者是install到python环境里,终于会生成一个so文件,接着import这个模块就能够使用了。
还有两点须要注意的是,python的垃圾自己主动回收策略是引用计数。以及线程安全操作,这些都能够添加到自己定义的模块中。
上面的样例中用C扩展了Python,我们还能够用Java扩展Jython,使用C#或者VB .NET扩展IronPython。如果在win32下,python还能够使用其COM(市场名字为ActiveX)操作Microsoft Office。
【Python】python扩展的更多相关文章
- Python 7 —— 扩展与嵌入
Python 7 —— 扩展与嵌入 所谓扩展是指,在Python当中调用其他语言,由于Python的问题主要是效率,这里的扩展主要是指扩展C C++程序(重点) 所谓嵌入是指,在其他语言当中可以调用P ...
- windows 下 使用codeblocks 实现C语言对python的扩展
本人比较懒就粘一下别人的配置方案了 从这开始到代码 摘自http://blog.csdn.net/yueguanghaidao/article/details/11538433 一直对Python扩展 ...
- Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)
我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...
- Python C++扩展
Python C++扩展 前段时间看了一篇文章,http://blog.jobbole.com/78859/, 颇有感触,于是就结合自己工作中的知识作了一个简单的Python移动侦测:移动侦测的算法使 ...
- Python3.x:python: extend (扩展) 与 append (追加) 的区别
Python3.x:python: extend (扩展) 与 append (追加) 的区别 1,区别: append() 方法向列表的尾部添加一个新的元素.只接受一个参数: extend()方法只 ...
- python基础扩展(二)
python基础扩展(二) 常用操作 1.startswith(以什么开始) endswith(y)什么结束 s='taiWanw39dd' print(s.startswith('t')) #意思是 ...
- Python的扩展接口[3] -> Matlab引擎 -> 使用 Python 调用 Matlab 程序
Python - Matlab 目录 Python-Matlab 引擎 Python-Matlab 数组 Python-Matlab 基本操作 Python-Matlab 调用 m 文件 Matlab ...
- python --- Python中的callable 函数
python --- Python中的callable 函数 转自: http://archive.cnblogs.com/a/1798319/ Python中的callable 函数 callabl ...
- Micro Python - Python for microcontrollers
Micro Python - Python for microcontrollers MicroPython
- 从Scratch到Python——python turtle 一种比pygame更加简洁的实现
从Scratch到Python--python turtle 一种比pygame更加简洁的实现 现在很多学校都开设了Scratch课程,学生可以利用Scratch创作丰富的作品,然而Scratch之后 ...
随机推荐
- UVALive 4128 Steam Roller 蒸汽式压路机(最短路,变形) WA中。。。。。
题意: 给一个由n*m个正方形格子组成的矩形,其中每个格子的边都是可以走的,长度给定,规定:如果在进入该路前需要拐弯,或者走完该路需要拐弯,都是需要付出双倍距离的(每条路最多算2倍).问从起点到终点的 ...
- 免费公共DNS服务器IP地址大全(2017年6月24日)
收集全球各个常用公共DNS服务器 IP地址,欢迎各位朋友评论补充! 国内常用公共DNS 114 DNS: (114.114.114.114: 114.114.115.115) 114DNS安全版 ...
- swift不同地方 命名空间module iOS
Objective-C没有命名空间,为了避免冲突,Objective-C的类型一般都会加上两到三个字母的前缀,比如Apple保留的NS和UI前缀,各个系统框架的前缀,各个系统框架的前缀SK(Store ...
- Java基础(十四)--装箱、拆箱详解
Java中基本数据类型都有相对应的包装类 什么是装箱?什么是拆箱? 在Java SE5之前,Integer是这样初始化的 Integer i = new Integer(10); 而在从Java SE ...
- 使用soapUI5.3.0调试webservice接口(参数为XML格式)
最近项目中经常要调试webservice接口,从朋友处了解到他们经常使用SoapUI,因此学习一下这个工具的使用,为避免遗忘,特地记录下来,分享分享... 下载 #####首先,下载SoapUI,我下 ...
- PyCharm 自动添加作者及时间
打开pycharm,快捷键ctrl + alt + s 打开模板设置自己所需内容 完整打开路径:file>settings>editor>code style>file and ...
- 零基础入门学习Python(28)--文件
知识点 Python中使用open(...)这个内置函数来打开文件,并返回文件对象 open()函数参数说明: open(file, mode='r', buffering=-1, encoding= ...
- nodejs学习(一) ---- nodejs + express应用生成器 快速创建应用
1.node安装及环境配置(自行百度) 2.express安装及配置 (自行百度) 3.通过应用生成器工具 express 快速创建应用骨架 全局安装应用生成器 : npm install exp ...
- python爬虫入门01:教你在 Chrome 浏览器轻松抓包
通过 python爬虫入门:什么是爬虫,怎么玩爬虫? 我们知道了什么是爬虫 也知道了爬虫的具体流程 那么在我们要对某个网站进行爬取的时候 要对其数据进行分析 就要知道应该怎么请求 就要知道获取的数据是 ...
- 第十八节:Scrapy爬虫框架之settings文件详解
# -*- coding: utf-8 -*- # Scrapy settings for maoyan project## For simplicity, this file contains on ...