用C语言程序扩展Python模块实例教程

有时候需要用C程序来扩展Python程序。什么情况下需要用C程序来扩展Python呢?就我肤浅的理解,至少有如下场景:

1. 效率问题:尽管Python在编写程序的效率上非常高,其执行效率也不错,不过有些对性能非常关键的地方,还是有需求用C代码来实现,然后在Python中调用C程序,这样性能可能会更高一些。

2. 充分利用优秀的C函数库:C语言世界中有些非常优秀的函数库(如:前面提及的libcurl),它们功能强大、性能优秀,如果能将这些C函数库进行简单的包装,然后就可以在Python中轻松调用,这样就非常好了。

根据官方指导文档,我写了个jay这个C扩展模块,里面有一个方法hello(用于给一个人打招呼^_^);需要一个C文件实现该模块的功能,需要一个setup.py脚本实现模块的编译安装部署。(setup.py是不是很熟悉呢? 在几乎每个Python库的源代码中都这个文件…)源代码都可以在: https://github.com/smilejay/python/tree/master/py2013 处直接获取。

1. C程序文件jaymodule.c的内容如下:(不详细解释其原理了,看文末的参考文档吧,我也担心我解释不清楚 ^_^)

 代码如下 复制代码
#include <Python.h>
 
static PyObject * jay_hello(PyObject *self, PyObject *args) {
        const char *person;
        int sts;
        if (!PyArg_ParseTuple(args, "s", &person))
                return NULL;
        printf("Hello, %s. I'm Jay.n", person );
        return Py_None;
/*
        sts = printf("Hello, %s. I'm Jay.n", person );
        return Py_BuildValue("i", sts);
*/
}
 
static PyMethodDef JayMethods[] = {
        {"hello",  jay_hello, METH_VARARGS,
        "Say hello to a person from Jay."},
        {NULL, NULL, 0, NULL}        /* Sentinel */
};
 
PyMODINIT_FUNC initjay(void) {
        PyImport_AddModule("jay");
        (void) Py_InitModule("jay", JayMethods);
}
 
 
int main(int argc, char *argv[]) {
        /* Pass argv[0] to the Python interpreter */
        Py_SetProgramName(argv[0]);
 
        /* Initialize the Python interpreter.  Required. */
        Py_Initialize();
 
        /* Add a static module
        Py_Exit(0);
}

2. setup.py这个构建和安装该模块的Python脚本如下:

 代码如下 复制代码
from distutils.core import setup, Extension
 
module1 = Extension('jay',
                    sources = ['jaymodule.c'])
 
setup(name = 'jay',
      version = '1.0',
      description = 'This is a demo package from Jay.',
      ext_modules = [module1])

3. 构建和安装方法很简单,就是传统的“sudo python setup.py install”:

 代码如下 复制代码
jay@jay-linux:~/workspace/python.git/py2013$ sudo python setup.py install
running install
running build
running build_ext
running install_lib
copying build/lib.linux-x86_64-2.7/jay.so -> /usr/local/lib/python2.7/dist-packages
running install_egg_info
Removing /usr/local/lib/python2.7/dist-packages/jay-1.0.egg-info
Writing /usr/local/lib/python2.7/dist-packages/jay-1.0.egg-info

4. 在Python中演示jay这个模块的效果,如下:

 代码如下 复制代码

jay@jay-linux:~$ python
Python 2.7.3 (default, Sep 26 2013, 20:03:06)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import jay
>>> jay.hello('Tom')
Hello, Tom. I'm Jay.
>>>

这里的演示,是让我的C模块能够在Python中动态加载;如果你有将这个库作为built-in的模块,直接加载Python解释器中,那么编译安装的方式有点不同,需要将自己的扩展模块加入到Python解释器的源码中,然后重新编译Python解释器。可参考官方文档:compilation-and-linkage

当然,这里是用Python2.7做演示的,Python3中的C扩展也是类似的(略有不同),如果你希望进一步了解Python3上的写法,请参考:http://docs.python.org/3/extending/extending.html

时间: 2024-09-18 07:51:07

用C语言程序扩展Python模块实例教程的相关文章

Python多线程实例教程_python

本文以实例形式较为详细的讲解了Python的多线程,是Python程序设计中非常重要的知识点.分享给大家供大家参考之用.具体方法如下: 用过Python的人都会觉得Python的多线程很类似于Java的多线程机制,但是比JAVA的多线程更灵活.在早期的Python多线程实现中,采用了thread模块.例如:   from time import ctime,sleep from thread import start_new_thread def loop1(): print "enter lo

Python迭代用法实例教程_python

本文实例讲述了Python中迭代的用法,是一个非常实用的技巧.分享给大家供大家参考借鉴之用.具体分析如下: 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们成为迭代(Iteration). 在Python中,迭代是通过for ... in来完成的,而很多语言比如C或者Java,迭代list是通过下标完成的,比如Java代码: for (i=0; i<list.length; i++) { n = list[i]; } 可以看出,Python的f

Python中zip()函数用法实例教程_python

本文实例讲述了Python中zip()函数的定义及用法,相信对于Python初学者有一定的借鉴价值.详情如下: 一.定义: zip([iterable, ...])zip()是Python的一个内建函数,它接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的list(列表).若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同.利用*号操作符,可以将list unzip(解压). 二.用法示例: 读者看看下面的例子,对

Python中apply函数的用法实例教程_python

一.概述: python apply函数的具体含义如下:  apply(func [, args [, kwargs ]]) 函数用于当函数参数已经存在于一个元组或字典中时,间接地调用函数.args是一个包含将要提供给函数的按位置传递的参数的元组.如果省略了args,任何参数都不会被传递,kwargs是一个包含关键字参数的字典.   apply()的返回值就是func()的返回值,apply()的元素参数是有序的,元素的顺序必须和func()形式参数的顺序一致 二.使用示例: 下面给几个例子来详

深入浅析 C++ 调用 Python 模块_C 语言

一般开发过游戏的都知道Lua和C++可以很好的结合在一起,取长补短,把Lua脚本当成类似动态链接库来使用,很好的利用了脚本开发的灵活性.而作为一门流行的通用型脚本语言Python,也是可以做到的.在一个C++应用程序中,我们可以用一组插件来实现一些具有统一接口的功能,一般插件都是使用动态链接库实现,如果插件的变化比较频繁,我们可以使用Python来代替动态链接库形式的插件(堪称文本形式的动态链接库),这样可以方便地根据需求的变化改写脚本代码,而不是必须重新编译链接二进制的动态链接库.灵活性大大的

Python内置函数的用法实例教程_python

本文简单的分析了Python中常用的内置函数的用法,分享给大家供大家参考之用.具体分析如下: 一般来说,在Python中内置了很多有用的函数,我们可以直接调用. 而要调用一个函数,就需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数.可以直接从Python的官方网站查看文档:http://docs.python.org/2/library/functions.html#abs 也可以在交互式命令行通过help(abs)查看abs函数的帮助信息. 调用abs函数: >>> a

PHP array_push() 函数实例教程与使用方法

PHP array_push() 函数实例教程与使用方法 定义和用法 该array_push ( )函数插入一个或多个元素的末尾一个数组. 语法 array_push(array,value1,value2...) 参数说明阵列必需的.指定一个数组value1要求.指定的值增加value2可选.指定的值增加 提示和说明提示:您可以添加一个值,或多达你喜欢. 注意:即使您已经字符串数组键,您的补充内容将allways有数字键. (见例2 )     <?php $a=array("Dog&q

PHP strchr() 函数实例教程

PHP strchr() 函数实例教程 定义和用法 该strchr ( )函数搜索首次出现了一系列内部其他字串. 这个函数返回其余的字符串(从匹配点) ,或FALSE ,如果该字符串搜索没有发现. 这一功能是一个别名的strstr ( )函数. 语法 strchr(string,search) Parameter Description string 必需的.指定字符串搜索 search 必需的.指定的字符串搜索.如果此参数是一个数字,它将寻求匹配的字符的ASCII值的数目 提示和说明注:此功能

php str_word_count 函数实例教程

定义和用法 该str_word_count ( )函数计数的数目字一个字符串. 语法 str_word_count(string,return,char) Parameter Description string 必需的.指定的字符串检查 return 任择.指定返回值的str_word_count ( )函数.可能值: 0 -默认.返回字数发现1 -返回一个数组的话从字串2 -返回一个数组在关键的立场是,这个词的字符串,和价值是实际的字 char 任择.指定特殊字符将被视为话.注:此参数是说在