码迷,mamicode.com
首页 > 编程语言 > 详细

使用Cython为Python写扩展1:初识Cython

时间:2014-06-18 17:48:59      阅读:382      评论:0      收藏:0      [点我收藏+]

标签:blog   code   http   tar   ext   com   

使用Cython为Python写扩展1:初识Cython

Cython使为Python写C扩展就如同写Python代码一样简单。广泛用于数学软件包,SAGE公司,作为执行快速,可扩展的运算。它提供了安全和可维护的方法通过自动生成所需代码来构建原生Python模块。

我们经常会使用Cython将C/C++实现的系统绑定到Python中,这样我们就可以使用Python来处理高级别逻辑,原生模块来处理底层代码。

关于示例

代码

http://git.oschina.net/erhuabushuo/learning-cython

版本:

  • Python:3.3
  • Cython:0.19

注意:如果你使用的版本不一致,可能需要对示例进行适当修改

安装Cython

我们先来安装Cython。将Cython想象成类似Bison, flex,或者GCC,它接受输入源代码并生成其他编译和链接代码:

  • Fedora: yum install Cython3
  • Ubuntu/Debian: apt-get install Cython3
  • curl -O http://www.cython.org/release/Cython-0.19.tar.gz tar xzvf Cython-0.19.tar.gz cd Cython-0.19 sudo python3 setup.py install
  • Windows http://wiki.cython.org/InstallingOnWindows .
  • pip: pip3 install cython

你好中国

我们通过以下来检查cython的安装

$ cython3 --version
Cython version 0.19

hello.pyx

print("你好中国!")

这里Cython代码仅简单打印出"你好中国!"

Makefile

all:
    cython3 -3 -o hello.c hello.pyx
    gcc -g -O2 -fpic -c hello.c -o hello.o `python3.3-config --cflags`
    gcc -g -O2 -shared -o hello.so hello.o `python3.3-config --libs`

编译链接

$ make

现在我们已经创建了hello.so模块。

使用

python3
Python 3.3.2+ (default, Feb 28 2014, 00:52:16) 
[GCC 4.8.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello
你好中国!
>>> 

我们直接通过import导入模块

解释

Cython使用.pyx和.pxd作为文件扩展名。现在我们仅关心.pyx文件。后面,我会介绍.pxd的使用。

我们来看看Cython是如何工作的

bubuko.com,布布扣

创建你自己的模块

现在已经看到了”你好中国“模块,让我们看看如何写你自己的模块,你可以链接你自己的一些代码,稍后,我们会介绍如何包装你的代码。

执行你的C代码

Cython时Python的超集,虽然语法和关键字都可相同工作,我们也应该弄清Python和Cython区别。让我们来构建类似hello-world风格模块,但做一些其他简单事情。

mycode.c

#include <stdio.h>

int myfunc(int a, int b)
{
    printf("现在我们在C代码\n");
    return a + b;
}

这是我们要调用的C代码,执行简单的运算两个数之和函数。现在我们使用Python来调用它。打开文件mycode.h,定义Cython的原型。

mycode.h

#ifndef __MYCODE_H__
#define __MYCODE_H__
extern int myfunc(int, int);
#endif //__MYCODE_H__

我们需要这样让Cython可以知道需要调用的函数原型。在实际中,你可能已经在项目头文件中定义了原型。新建mycodecpy.pyx,写入如下代码:

cdef extern from "mycode.h":
    cdef int myfunc(int, int)

def callCfunc():
    print(myfunc(1, 2))

在Cython代码里,我们定义了我们想使用的C代码,cdef关键字标识要链接的C代码。现在我们已经定义了所要使用的头文件,我会详细说明Python如何调用原生代码,由于直接调用C代码时危险的。所以,Cython为我们处理所有类型转换问题。基本函数包装,callCfunc,调用myfunc函数并且传递整型,然后简单打印结果。

用以下命令编译:

$ cython3 mycodecpy.pyx
$ gcc -g -O2 -fpic -c mycode.c -o mycode.o
$ gcc -g -O2 -fpic -c mycodecpy.c -o mycodecpy.o `python3.3-config --cflags`
$ gcc -shared -o mycodecpy.so mycode.o mycodecpy.o `python3.3-config --libs`

我们要链接mycode.c代码。将所有C文件编译为对象文件,然后将所有对象文件链接成一个二进制文件。因此,所以确保你链接了所有需要对象文件。

$ python3
>>> from mycodecpy import callCfunc
>>> callCfunc()
现在我们在C代码
3

所以,我们现在已经编译并且通过Python代码来调用我们原生代码。你卡亚开始绑定一些其他一些原生模块了。

类型转换

你也许注意到了我们调用直接调用Cython函数而没带参数,如果我们想带参数呢?

def callCfunc(int x, int y):
    print(myfunc(x, y))   

现在我们增加了两个int参数到我们定义的Python包装函数中。这里需要Python代码类型安全的转换PyObjects为C类型。当你创建一个Python整型对象。该类型不是integer而是PyObject。如果你想在C中使用,你需要通过Python C API来获取该值,但是Cython自动给你做了该事情。例如,如果你传递了不合法参数,你将会得到:

>>> callCfunc(1, ‘string‘)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "mycodecpy.pyx", line 4, in mycodecpy.callCfunc (mycodecpy.c:687)
    def callCfunc(int x, int y):
TypeError: an integer is required

添加更多类型安全对象,你发现会提高速度,代码也会更漂亮。因为Cython编译器可以更加优化代码避免使用Python调用。

使用Cython为Python写扩展1:初识Cython,布布扣,bubuko.com

使用Cython为Python写扩展1:初识Cython

标签:blog   code   http   tar   ext   com   

原文地址:http://www.cnblogs.com/erhuabushuo/p/3790894.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!