`
dato0123
  • 浏览: 910908 次
文章分类
社区版块
存档分类
最新评论

使用C语言扩展Python(一)

 
阅读更多

开发环境:Ubuntu9.10,python2.6,gcc4.4.1

1,ubuntu下的python运行包和开发包是分开的,因此需要在新利得里面安装python-all-dev,从而可以在代码中引用python的头文件和库。

2.下面是一个最简单的可以供python调用的c扩展模块,假设c程序文件名为foo.c:

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->#include<Python.h>

staticPyObject*foo_bar(PyObject*self,PyObject*args){
Py_RETURN_NONE;
}

staticPyMethodDeffoo_methods[]={
{
"bar",(PyCFunction)foo_bar,METH_NOARGS,NULL},
{NULL,NULL,
0,NULL}
};

PyMODINIT_FUNCinitfoo(){
Py_InitModule3(
"foo",foo_methods,"Myfirstextensionmodule.");
}

我们可以将上述模块分成3个部分:1)c模块想对外暴露的接口函数。2)提供给外部的python程序使用的一个c模块函数名称映射表。3)c模块的初始化函数。模块的第一行将Python.h引入到模块中,这个文件将使得你的模块可以hook进python的解释器,从而可以为外部的python程序所使用。

c模块中的函数签名一般有下列三种形式:

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->PyObject*MyFunction(PyObject*self,PyObject*args);
PyObject
*MyFunctionWithKeywords(PyObject*self,PyObject*args,PyObject*kw);
PyObject
*MyFunctionWithNoArgs(PyObject*self);

一般我们使用的是第一种方式,函数的参数将会一个元组(tuple)的形式传进来,因此我们在c模块的函数中需要对其进行解析。Python中不能象c语言一样声明一个void类型的函数,如果你不想函数返回一个值的话,那就返回一个NONE,在这里我们可以通过Python头文件中的一个宏Py_RETURN_NONE来实现。

C模块中的函数名称其实对外部来说是不可见的,因此可以随便你命名,一般我们可以使用static函数(这在C语言里表示在当前文件以外是不可见的)。本文函数命名方式采用模块名加上函数名,例如foo_bar,这表示在模块foo中会有一个bar函数。然后就是函数映射表了,它是一个PyMethodDef结构体数组,

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->structPyMethodDef{
char*ml_name;
PyCFunctionml_meth;
intml_flags;
char*ml_doc;
};

第一个成员ml_name是函数名,当我们在外部的Python代码中使用此模块时利用这个名称进行函数调用。ml_meth是函数地址。ml_flags告诉解释器ml_meth将会使用上述三种方法签名的哪一种,一般设置为METH_VARARGS,如果你想允许关键字参数,则可以将其与METH_KEYWORDS进行或运算。若不想接受任何参数,则可以将其设置为METH_NOARGS.最后,ml_doc字段是函数的注释文档信息,最好还是写几句吧,不然会被鄙视的。。。另外,这个表必须以{NULL,NULL,0,NULL}这样一条空记录结尾。

模块的初始化函数是在模块被加载时被Python解释器所调用的,如果你的模块名为foo,则要求命名为initfoo.Py_InitModule3函数一般用来定义一个模块。

3,现在我们来将foo.c文件编译为一个扩展模块,使用下述命令进行编译:

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->gcc-shared-I/usr/include/python2.6foo.c-ofoo.so

注意shared object的名称必须和传给Py_InitModule3函数的字符串一致,另一种可选的方式是加上module后缀,因此上述foo模块可以命名为foo.so或foomodule.so。

4,上面的编译方式可以完成任务,但更好的生成扩展模块的方法是使用distutils。首先写一个setup.py脚本:

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->fromdistutils.coreimportsetup,Extension
setup(name
='foo',version='1.0',ext_modules=[Extension('foo',['foo.c'])])

然后执行下述命令进行build:

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->python./setup.pybuild

这会在当前目录下生成一个build子目录,其中包含了中间生成的foo.o以及最后生成出来的foo.so。当然,最简单的方法是使用下述命令进行模块的生成和安装:

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->python./setup.pyinstall

注:由于需要获得dist-packages的写权限,最好先切换到root用户,如果直接使用su切换出现下面的错误:

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->su:Authenticationfailure

则为root用户设置一个新密码:

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->sudopasswdroot

再用新密码切换到root用户。查看build时的详细情况,我们可以发现这么一句:

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->copyingbuild/lib.linux-i686-2.6/foo.so->/usr/local/lib/python2.6/dist-packages

这是将生成的模块拷贝到/usr/local/lib/python2.6/dist-packages下了,这样就将我们的foo模块安装到系统中了,我们可以验证如下,在python命令行中,

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->importfoo
dir(foo)

结果如下:

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->['__doc__','__file__','__name__','__package__','bar']

呵呵,不错吧,这个foo模块现在已经和其他系统模块一样了,原因就在于dist-packages是在sys.path这个路径中的,
5,现在我们手上已经有一个生成并安装好的C扩展模块了,剩下的就是在python代码中引入这个新模块,并调用它的方法

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->importfoo
foo.bar()

当然,由于在c模块中的bar函数里,我们目前什么都还没做,所以现在啥都没有,在下一篇中我们实现:1)从python脚本里向C模块中传递参数。2)从C模块中返回值给外部的Python脚本

夜已经深了,这个python和c/c++,java相结合系列的第一篇就暂时写到这里。。。

分享到:
评论

相关推荐

    用C语言扩展Python的功能

    用C语言扩展Python的功能

    用C语言扩展Python的功能.pdf

    用C语言扩展Python的功能.pdf

    C语言扩展Python学习记录.zip

    C语言扩展Python学习记录

    使用C语言扩展Python程序的简单入门指引

    主要介绍了使用C语言扩展Python程序的简单入门指引,来自于IBM官网网站技术文档,需要的朋友可以参考下

    用C语音编写python的扩展模块,也就是python调c库

    NULL 博文链接:https://8366.iteye.com/blog/1575189

    硬件SPI 作为 Python 的 C 扩展_C语言_python_代码_下载

    SPI-Py:硬件 SPI 作为 Python 的 C 扩展 示例用法 下面的命令可以在test_script.py文件中找到。 安装库后,通过以下方式将 spi 模块导入 Python 代码: 更多详情、使用方法,请下载后阅读README.md文件

    Extend_Python:C语言扩展Python学习记录

    Extend Python with C 实际上ctypes、Python C API或者基于API的Cython,逻辑都是: 接收Python对象-&gt;转换为C对象-&gt;调用C函数-&gt;返回值转换为Python对象-&gt;返回 的流程,较为值得关切的几点是: 指针传参问题 数组传递...

    使用C语言来扩展Python程序和Zope服务器的教程

    最可能的是您有一个已能帮您做些事的现成的 C 库,但是您对把它转换成 Python 却不感兴趣。此外,由于 Python 是解释性语言,所以任何被大量调用的 Python 代码都将降低您的速度。因此,即使您已经用 Python 写了...

    课程设计-使用python对c语言代码进行静态分析.zip

    课程设计-使用python对c语言代码进行静态分析.zip 项目资源具有较高的学习借鉴价值,也可直接拿来修改复现。可以在这些基础上学习借鉴进行修改和扩展,实现其它功能。 可下载学习借鉴,你会有所收获。 课程设计-使用...

    数据结构(基于 C++ 语言) + 算法 (基于 C语言 和 Python语言).zip

    对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同...

    用Cython加速Python到“起飞”(推荐)

    由于Python固有的性能差的问题,用C扩展Python成为提高Python性能常用方法,Cython算是较为常见的一种扩展方式。 我们可以对比一下业界主流的几种Python扩展支持C语言的方案: 有试用版水印,是因为穷T_T ctypes是...

    如何用C代码给Python写扩展库(Cython)

    之前一篇文章里提到了利用Cython来编译Python,这次来讲一下如何用Cython给Python写扩展库。 两种语言混合编程,其中最重要的是类型的传递。 我们用一个简单的例子进行入门:这次的目标是用C语言写一个Numpy的加法和...

    用python创建手写C扩展模块基本过程

    用python创建手写C扩展模块基本过程 编写接口代码主要分为四步: 1. 包含Python的头文件 2. 为每个模块的每一个函数增加一个型如PyObject* Module_func()的包装函数。 3. 为每个模块增加一个型如PyMethodDef ...

    Python 2和Python 3的介绍

    Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。Python也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码或机器...

    Python变量的输入输出-格式化输出整数变量

    Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。Python也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码或机器...

    python 3.10.5 Windows 64位安装包

    Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。 [4] Python 也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码...

    python程序的格式以及扩展名

    Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。Python也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码或机器...

Global site tag (gtag.js) - Google Analytics