【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 PythonType 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之后 ...
随机推荐
- SpringBoot传参转换枚举
有时候,我们传参的时候,希望使用枚举类来当作参数 public enum VipEnum { HUANG(1, "黄钻"), HONG(2, "红钻"); pr ...
- bootparam - 介绍Linux核心的启动参数
描叙 Linux 核心在启动的时候可以接受指定的"命令行参数"或"启动参数".在通常情况下,由于核心有可能无法识别某些硬件,或可能将某些硬件识别为不正确的配置, ...
- oracle char 多位,引发的问题
我在表字有一字段type 类型为char(1),一开始用的还好,后来,char(1)不够用了,于是将char(1),变为char(2). 我做了一个字典表,来对应type,可是,总是查不到数据,最后, ...
- js 上传图片、压缩、旋转
亲测 <!doctype html> <html> <head> <meta charset="utf-8"> <title& ...
- Android图像处理之Bitmap类(1)
Bitmap是Android系统中的图像处理的最重要类之一.用它可以获取图像文件信息,进行图像剪切.旋转.缩放等操作,并可以指定格式保存图像文件.本文从应用的角度,着重介绍怎么用Bitmap来实现这些 ...
- 趣味ACM题——圣骑士的斩杀
题目来源于山东省第七届ACM大学生程序设计竞赛(Execution of Paladin) 题目描述 鱼人是炉石里的一支强大种族,在探险者协会里,圣骑士有了一张新牌,叫亡者归来,效果是召唤本轮游戏中7 ...
- nginx搭建静态资源服务器
nginx配置访问前端工程 1.前端工程目录 crm-view |-- view |-- user.html 2.工程位置 C:\Users\Administrator\Desktop\CRM系统\c ...
- find -print0和xargs -0原理及用法
平常我们经常把find和xargs搭配使用,例如: find . -name "*.txt" | xargs rm 但是这个命令如果遇到文件名里有空格或者换行符,就会出错.因为xa ...
- Laravel核心解读 -- 扩展用户认证系统
扩展用户认证系统 上一节我们介绍了Laravel Auth系统实现的一些细节知道了Laravel是如何应用看守器和用户提供器来进行用户认证的,但是针对我们自己开发的项目或多或少地我们都会需要在自带的看 ...
- Python之数字
Python之数字 int(数字)===>在Python3中,int没有范围,在Python2中,int超出范围就叫长整型(Long). 浮点运算:单精度 float 双精度 double a: ...