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("");
}

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。

时间: 2024-11-02 00:58:11

python扩展的相关文章

python扩展实现方法--python与c混和编程

Reference: http://www.cnblogs.com/btchenguang/archive/2012/09/04/2670849.html python 头文件在的位置:/usr/include/python2.7                                  /usr/local/include/python2.7 前言(更新:更方便易用的方式在http://www.swig.org/tutorial.html) 大部分的Python的扩展都是用C语言写的,

vs2013在图像处理中的应用(7):开发Python扩展

快乐虾 http://blog.csdn.net/lights_joy/(QQ群:Visual EmbedLinux Tools 375515651) 欢迎转载,但请保留作者信息 很久没有摸图像处理的东西了,近期刚好需要有此需求,希望能够有一个比较好用的开发环境.在学校的时候做图像处理一直用的是matlab,不过现在正好在做VELT的开发,尝试用vs2013+python构造一个适合于自己用的开发环境. 在图像处理中,虽然已经可以用python操纵opencv完成一些算法,但总免不了需要自己写一

window下python 扩展库安装 使用第三方镜像源

0.前言 由于python的官方镜像位于国外,若使用pip或者easy_install安装第三方插件时或许会被限制,甚至连easy_install或pip也无法安装,例如在windows环境下运行ez_setup.py 安装easy_install,可能遇到下图这样尴尬的情况. 图1 运行ez_setup.py失败 遇到这种问题可以”转战“国内的第三方镜像,问题便可迎刃而解.例如豆瓣镜像——http://pypi.douban.com/simple/ 1.安装easy_install 先安装ea

python基础:python扩展包的安装方式

python扩展包有三种安装方式: 1. pip安装方式.python3默认自带pip,无需另外安装:在python2.7版本上默认为easy_install安装工作进行安装,如果需要使用pip安装,需要自行下载安装(可以从http://www.pip-installer.org网站下载). 2. 系统自带的包安装管理工具. 3. 从源代码安装. 使用pip安装:在command命令行中输入:pip install 包名,例如:pip install flask 使用pip安装指定版本:在com

监控开发之用python扩展dstat插件自定义实时监控

dstat是一个python开源的实时监控工具,一般是用来做系统性能监控的.咱们这里只是提他的自定义插件开发,用来打造自己的dstat. 有朋友可能还没清楚是啥意思, 咱们查看系统的状体状态有人喜欢用vmstat,也有人喜欢用dstat.相比来说dstat的功能模块更全一点是,这里还只是说查看系统性能方面的 !   如果想一边查看,系统的各方面性能指标,还想看你应用的一些个负载相关,比如某个程序的负载,mongodb的锁lock百分比,mysql连接数...   懂了吧 ! 下面是dstat的插

python扩展实现方法--python与c混和编程 转自:http://www.cnblogs.com/btchenguang/archive/2012/09/04/2670849.html

前言 需要扩展Python语言的理由: 创建Python扩展的步骤 1. 创建应用程序代码 2. 利用样板来包装代码 a. 包含python的头文件 b. 为每个模块的每一个函数增加一个型如PyObject* Module_func()的包装函数 c. 为每个模块增加一个型如PyMethodDef ModuleMethods[]的数组 d. 增加模块初始化函数void initMethod() 3. 编译与测试 a. 创建setup.py b. 通过运行setup.py来编译和连接你的代码 c.

.windows安装使用这些偏底层的Python扩展太

.windows安装使用这些偏底层的Python扩展太不爽了,怎么彻底解决 error: Unable to find vcvarsall.bat呢? 1.不要按网上说的,安装MinGW,然后在“..python安装路径...\Lib\distutils”下新建一个文件distutils.cfg,在这文件里面指定编译器为mingw32 如: [build] compiler=mingw32 原因是什么,可以百度一下mingw是什么,毕竟不是GCC,又不如VC接windows的地气,编译出来的东西

使用Python扩展NotePad++

要使用Python扩展NotePad++,首先需要为NotePad++安装Python Script插件,NotePad++插件的安装方法可以参考这里. 安装了Python Script插件后,在菜单的Plugins下就会看到Python Script菜单了. Python Script介绍 点击Plugins->Python Script->New Script菜单,打开的目录就是用户的Python脚本存放的目录.将Python脚本放到该目录下后,在Python Script下的Script

windows下Python扩展问题error: Unable to find vcvarsall.bat

由于对于Windows下Python扩展不熟,今天遇到一个安装问题,特此做个tag.解决方式在stackoverflow上,网址例如以下: http://stackoverflow.com/questions/2817869/error-unable-to-find-vcvarsall-bat

windows编译python扩展Unable to find vcvarsall

在windows平台上安装比如twisted,gevent时会报出该错误,在网上找了一些解决办法大多都是说将编译器修改为mingw32,而我觉得此办法稍显麻烦,刚好电脑上安装有VisualStudio,找了一圈发现只需设置环境变量即可,此法正合我意. 操作步骤如下: 打开Visual Studio工具中的Visual Studio 命令提示 Python 2.7 会搜索 Visual Studio 2008.如果你电脑上没有这个版本的话,比如: * Visual Studio 2010,在cmd