Chinaunix首页 | 论坛 | 博客
  • 博客访问: 409832
  • 博文数量: 42
  • 博客积分: 1030
  • 博客等级: 准尉
  • 技术积分: 816
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-06 17:16
文章分类

全部博文(42)

文章存档

2013年(1)

2012年(41)

分类: Python/Ruby

2012-11-30 11:08:04

使用Python可以快速的搭建软件原型和框架,但是在对性能要求比较严格的地方,就需要使用C/C++扩展来提高性能。或是在需要对底层的硬件进行操作的时候就必须使用C语言了。

C/C++模块需要使用进行封装,然后编译成动态链接库的形式供Python导入调用,步骤:

例如一个C文件(hello.c)需要导入到Python中使用:

  1. #include <stdio.h>

  2. void test(void)
  3. {
  4.     fprintf(stdout, "Hello C\n");
  5.     return;
  6. }

方法1:手工编译链接

  • 编写"hello.i"接口文件,%module之后跟随模块的名称,%{和%}之间放置包含的头文件,然后在后面跟随函数的声明,详细的内容参考
    1. %module hello
    2. %{
    3. #include
    4. %}
    5. extern void test(void);

  • 使用SWIG生成包裹文件
    1. swig -python hello.i
    使用swig命令之后会生成"hello.py"和"hello_wrap.c"这两个文件
  • 编译C文件和包裹文件(需要知道python在系统中的安装路径)
    1. gcc -c hello.c
    2. gcc -I /usr/include/python2.6 -c hello_wrap.c

    以上命令是在Linux环境中使用GCC编译的,在其他系统中也类似
  • 将C文件和包裹文件编译成动态链接库,得到动态链接库文件"_hello.so"
    1. gcc -shared hello.o hello_wrap.o -o _hello.so

方法2:使用Distutils编译扩展
  • 建立Distutils安装脚本setup.py
    1. from distutils.core import setup, Extension

    2. setup(name='hello', version='1.0', ext_modules = [Extension('_hello', ['hello.c', 'hello.i'])])
    Extension中第一个参数的名字就是下一步生成的动态链接库所使用的名字"_hello.so"
  • 编译扩展得到Python可以使用的动态链接库文件"_hello.so"
    1. python setup.py build_ext --inplace

通过以上提供的2种方法都可以得到一个 Linux动态链接库“so”文件,将得到的"_hello.so"模块放在当前目录中既可以在python命令行中进行测试例如:

  1. Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
  2. [GCC 4.4.5] on linux2
  3. Type "help", "copyright", "credits" or "license" for more information.
  4. >>> import _hello as c_test
  5. >>> c_test.test()
  6. Hello C
  7. >>>

注意:生成的动态链接库的名字要以接口文件(*.i)中的%module中的名字之前加“_”来生成,如例子中模块的名字为“hello”那么生成的动态链接库的名字要为“_hello.so”否则在python中导入的时候会报错:“ImportError: dynamic module does not define init function (inithello)”这是因为在导入之后要调用初始化函数,而初始化函数的名字命名格式是“init_modulename”


[参考]:
《Python 基础教程》17章扩展Python、18章打包

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