知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516
全部博文(315)
分类: Python/Ruby
2012-02-22 21:54:49
Python扩展
这个 部分主要说的是c中如何“扩展”python---其实这是把c代码包装到python中去,同时c和python如何传递数据,共享数据等等。利用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的语言,工具---就是生成我们上面的包装好的c的python扩展代码的swig等工具,就不管啦。学到了再说吧,这章扫的快啦,没怎么深入…
Python核心编程先告一个段落了,我下来准备去完善我的document_hens这个文档小项目,方便以后我的练习和开发使用;同时我要开始复习c语言了,做些题之类的;至于c++这块,先搁着,工作后抽时间去学习,现在还不是很清楚进公司后做什么开发;希望有意思,能学到东西!