Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2563661
  • 博文数量: 315
  • 博客积分: 3901
  • 博客等级: 少校
  • 技术积分: 3640
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-08 15:32
个人简介

知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516

文章分类

全部博文(315)

文章存档

2019年(2)

2018年(1)

2016年(7)

2015年(32)

2014年(39)

2013年(109)

2012年(81)

2011年(44)

分类: Python/Ruby

2012-02-22 21:54:49

                                                 Python扩展

       这个 部分主要说的是c中如何“扩展”python---其实这是把c代码包装到python中去,同时cpython如何传递数据,共享数据等等。利用python的引入模块特性,来测试我们的c代码,管理大型的项目,这是python的扩展和内嵌是不同的哦;当然至于一些很高深的应用,现在不懂啦!(这里我们没有安装python-dev,所以没有Python.h这样的文件,所以没办法测试,编译不会通过的啦

//file: Extest1.c

 

#include

#include

#include

 

#include "Python.h"

 

#define BUFFSIZE 1024

 

int fac(int n)

{

    if (n < 2) return (1); //0!=1!=1

    return (n) * fac(n-1);

}

 

char *reverse(char *s)

{

    register char t; //我们在多次使用同一个变量,这时可以暗示编译器将其变量放到寄存器中,以加快访问速度;

    char *p = s;

    char *q = (s + (strlen(s)-1));

 

    while (p < q)

    {

        t = *p;

        *p++ = *q;

        *q-- = t;

    }

    return s;

}

 

//以下是fac代码的python封装化,这样我们就可以在python中调用c模块了;

//代码可以简化,去除中间变量亦可减少内存使用;

static PyObject *Extest_fac(PyObject *self, PyObject *args)

{

    int res;

    int num;

    PyObject *retval; //返回值为PyObject对象;

 

    res = PyArg_ParseTuple(args, "i", &num); //python args to c

    if (!res){

        return NULL;

    }

 

    res = fac(num);

    retval = (PyObject *)Py_BuildValue("i", res); //c data to python objects && return"i"表示我们希望的时整型数据;

 

    return retval;

}

 

static PyObject *Extest_reverse(PyObject *self, PyObject *args)

{

    char *orig_str;

    char *dupe_str;

   

    if (!PyArg_ParseTuple(args, "s", &orig_str)) //"s"表示我们使用字符串

        return NULL;

    //return (PyObject *)Py_BuildValue("ss", orig_str, dupe_str = reverse(strdup(orig_str))); //strdup对字符串进行复制;我们同时返回原始字符串和反转后的字符串;"ss"表示两者希望作为字符串进行转换;

    retval = (PyObject *)Py_BuildValue("ss", orig_str, dupe_str = reverse(strdup(orig_str))); //strdup对字符串进行复制;我们同时返回原始字符串和反转后的字符串;"ss"表示两者希望作为字符串进行转换;

    free(dupe_str); //注意使用后需要释放内存,否则内存泄漏

   

    return retval;

}

 

//这是第二步,为模块增加PyMethodDef函数;

//METH_VARARGS常量表示参数以tuple形式传入;如果使用PyArg_ParseTupleAndKeywords()解析命名参数,需要改为METH_VARARGS & METH_KEYWORDS;

static PyMethodDef ExtestMethods[] = {

    {"fac", Extest_fac, METH_VARARGS},

    {"doppel", Extest_reverse, METH_VARARGS},

    {NULL, NULL},

};

 

//最后一步,增加模块初始化函数;

void initExtest()

{

    Py_InitModule("Extest", ExtestMethods);

}

 

/* 测试的main函数可以更名为test,同时修改参数;

 * 同样把该test函数利用pyton的方式包装起来;

 * 记住包装后需要在PyMethoDef数组中添加该函数;

 * 在导入import Extest模块的时候,就可以调用Extest.test()来进行c代码测试

int main(int argc, const char *argv[])

{

    char s[BUFFSIZE];

    printf("4! == %d\n", fac(4));

    printf("8! == %d\n", fac(8));

   

    strcpy(s, "abcdef");

    printf("reversing 'abcdef', we get '%s'\n", reverse(s));

 

 

    return 0;

}

*/

 

下面就利用setup.py来编译我们的模块了:

#!/usr/bin/env python

# -*- coding: UTF-8 -*-

 

from distutils.core import setup, Extension

 

MOD = 'Extest'

 

if __name__ == "__main__":

setup(name = MOD, ext_modules=[Extension(MOD, sources=['Extest1.c'])])

 

 运行前后情况:(运行后会多出一个build目录的)

huanglei@ubuntu:~/python/extend$ ls

Extest1  Extest1.c

 

huanglei@ubuntu:~/python/extend$ python setup.py build

running build

running build_ext

building 'Extest' extension

gcc -pthread -fno-strict-ali……..

…………………………….

 

huanglei@ubuntu:~/python/extend$ ls

build  Extest1  Extest1.c  setup.py

 

至于后面的相关话题提到的其他混合python的语言,工具---就是生成我们上面的包装好的cpython扩展代码的swig等工具,就不管啦。学到了再说吧,这章扫的快啦,没怎么深入

 

       Python核心编程先告一个段落了,我下来准备去完善我的document_hens这个文档小项目,方便以后我的练习和开发使用;同时我要开始复习c语言了,做些题之类的;至于c++这块,先搁着,工作后抽时间去学习,现在还不是很清楚进公司后做什么开发;希望有意思,能学到东西!

阅读(1696) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~