当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扩展的更多相关文章

  1. Python 7 —— 扩展与嵌入

    Python 7 —— 扩展与嵌入 所谓扩展是指,在Python当中调用其他语言,由于Python的问题主要是效率,这里的扩展主要是指扩展C C++程序(重点) 所谓嵌入是指,在其他语言当中可以调用P ...

  2. windows 下 使用codeblocks 实现C语言对python的扩展

    本人比较懒就粘一下别人的配置方案了 从这开始到代码 摘自http://blog.csdn.net/yueguanghaidao/article/details/11538433 一直对Python扩展 ...

  3. Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)

    我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...

  4. Python C++扩展

    Python C++扩展 前段时间看了一篇文章,http://blog.jobbole.com/78859/, 颇有感触,于是就结合自己工作中的知识作了一个简单的Python移动侦测:移动侦测的算法使 ...

  5. Python3.x:python: extend (扩展) 与 append (追加) 的区别

    Python3.x:python: extend (扩展) 与 append (追加) 的区别 1,区别: append() 方法向列表的尾部添加一个新的元素.只接受一个参数: extend()方法只 ...

  6. python基础扩展(二)

    python基础扩展(二) 常用操作 1.startswith(以什么开始) endswith(y)什么结束 s='taiWanw39dd' print(s.startswith('t')) #意思是 ...

  7. Python的扩展接口[3] -> Matlab引擎 -> 使用 Python 调用 Matlab 程序

    Python - Matlab 目录 Python-Matlab 引擎 Python-Matlab 数组 Python-Matlab 基本操作 Python-Matlab 调用 m 文件 Matlab ...

  8. python --- Python中的callable 函数

    python --- Python中的callable 函数 转自: http://archive.cnblogs.com/a/1798319/ Python中的callable 函数 callabl ...

  9. Micro Python - Python for microcontrollers

    Micro Python - Python for microcontrollers MicroPython

  10. 从Scratch到Python——python turtle 一种比pygame更加简洁的实现

    从Scratch到Python--python turtle 一种比pygame更加简洁的实现 现在很多学校都开设了Scratch课程,学生可以利用Scratch创作丰富的作品,然而Scratch之后 ...

随机推荐

  1. day25-1 网络架构与互联网组成

    目录 网络架构 单机架构 CS架构 数据放在服务端和客户端的利与弊 BS架构 互联网和互联网的组成 互联网的硬件组成 互联网的软件组成 网络架构 单机架构 应用领域: 单机游戏 CS架构 基于网络,应 ...

  2. CAD交互绘制带周长面积的矩形框(com接口)

    主要用到函数说明: _DMxDrawX::DrawLine 绘制一个直线.详细说明如下: 参数 说明 DOUBLE dX1 直线的开始点x坐标 DOUBLE dY1 直线的开始点y坐标 DOUBLE ...

  3. Java集合(三)--Collection、Collections和Arrays

    Collection: Collection是集合类的顶级接口,提供了对集合对象进行基本操作的通用接口方法.Collection接口的意义是为各种具体的集合提供了最大化 的统一操作方式,其直接继承接口 ...

  4. li标签和checkbox绑定

    参考原文:https://www.cnblogs.com/youxin/p/3885496.html 我们经常需要li或span包含一个checkbox,不管点击checkbox或li都会触发相应的事 ...

  5. mybatis保存时将数据库自动生成的主键返回

    场景 保存订单数据和订单详情数据时需要将订单的主键作为关联子段添加到明细表中,需要将保存订单时的主键返回给供保存明细表时使用 添加xml中新增数据时的配置 <insert id="in ...

  6. DNS服务器原理简述、搭建主/从DNS服务器并实现智能解析

    1. TLD:Top Level Domain 顶级域名 组织域:.com, .net, .org, .gov, .edu, .mil 国家域:.iq, .tw, .hk, .jp, .cn, ... ...

  7. Vue实例方法之事件的实现

    开始 这段时间一直在看vue的源码,源码非常多和杂,所以自己结合资料和理解理出了一个主线,然后根据主线去剥离其他的一些知识点,然后将各个知识点逐一学习.这里主要是分析的Vue事件处理的实现. 正文 一 ...

  8. aggregate和annotate方法使用详解与示例

    aggregate和annotate方法的使用场景 Django的aggregate和annotate方法属于高级查询方法,主要用于组合查询.当我们需要对查询集(queryset)的某些字段进行计算或 ...

  9. python 类的装饰器

    我们知道,在不改变原有代码的基础上,我们可以使用装饰器为函数添加新的功能.同理,一切皆对象,我们也可以使用装饰器为类添加类属性.what? def deco(obj): obj.x = 1 obj.y ...

  10. SpringMVC Controller的返回类型

    Controller的三种返回类型中 ModelAndView类型 带数据带跳转页面 String 跳转页面不带数据 void 通常是ajax格式请求时使用 1返回ModelAndView contr ...