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


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

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

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

关于示例

代码

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

版本:

Python:3.3Cython:0.19

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

安装Cython

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

Fedora: yum install Cython3Ubuntu/Debian: apt-get install Cython3curl -O http://www.cython.org/release/Cython-0.19.tar.gztar xzvf Cython-0.19.tar.gzcd Cython-0.19sudo python3 setup.py installWindows http://wiki.cython.org/InstallingOnWindows .pip: pip3 install cython

你好中国

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

$ cython3 --versionCython 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模块。

使用

python3Python 3.3.2+ (default, Feb 28 2014, 00:52:16) [GCC 4.8.1] on linuxType "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

评论关闭