標籤:

快速教程:使用Cython來擴展Python/NumPy庫

作者:monitor1379

原文鏈接:jianshu.com/p/1918e5805

正文共2583個字,7張圖,預計閱讀時間:7分鐘。

前言

整個快速教程直接上例子,具體對Cython的使用可以看參考文章。以下工作均在Windows 10 + Python 2.7 + NumPy 1.11.0 + Cython 0.24 版本上進行。

正文

準備工作

假設現在我們用C實現了一個可以用在數組上的cos函數,函數原型如下:

// 對in_array中的前size個數求cos值,並存放在out_array對應位置上

void cos_doubles(double * in_array, double * out_array, int size);

那麼總共需要4個文件:

cos_doubles.c,C源文件。

cos_doubles.h,C頭文件。

_cos_doubles.pyx,Python的C擴展文件。(注意:之所以前面加個"_"下劃線,是因為使用Cython編譯打包後會對pyx文件生成同名的c文件,為了避免覆蓋掉原來的cos_doubles.c文件,此處加個下劃線)

setup.py,負責管理編譯、打包工作的「配置」腳本。

下面給出4個文件的源代碼:

cos_doubles.c

#include "cos_doubles.h"n#include <math.h>nn/* Compute the cosine of each element in in_array, storing the result inn* out_array. */nvoid cos_doubles(double * in_array, double * out_array, int size){n int i;n for(i=0;i<size;i++){n out_array[i] = cos(in_array[i]);n }n}n

cos_doubles.h

#ifndef _COS_DOUBLES_Hnn#define _COS_DOUBLES_Hnvoid cos_doubles(double * in_array, double * out_array, int size);n#endifn

cos_doubles.pyx

""" Example of wrapping a C function that takes C double arrays as input usingnn the Numpy declarations from Cython """nn# import both numpy and the Cython declarations for numpynimport numpy as npncimport numpy as npnn# if you want to use the Numpy-C-API from Cythonn# (not strictly necessary for this example)nnp.import_array()nn# cdefine the signature of our c functionncdef extern from "cos_doubles.h":n void cos_doubles (double * in_array, double * out_array, int size)nn# create the wrapper code, with numpy type annotationsndef cos_doubles_func(np.ndarray[double, ndim=1, mode="c"] in_array not None,n np.ndarray[double, ndim=1, mode="c"] out_array not None):n cos_doubles(<double*> np.PyArray_DATA(in_array),n <double*> np.PyArray_DATA(out_array),n in_array.shape[0])n

setup.py

from distutils.core import setup, Extensionimport numpyfrom Cython.Distutils import build_extnnsetup(n cmdclass={build_ext: build_ext},n ext_modules=[Extension("cos_doubles",n sources=["_cos_doubles.pyx", "cos_doubles.c"],n include_dirs=[numpy.get_include()])],n)n

編譯打包

在命令行窗口中進入到上述文件所在同級目錄,輸入:

>> python setup.py build_ext -i

參數-i表示inplace,即在同級目錄下生成Python可調用模塊pyd文件。

build過程如下:

build過程

然後可以看見在同級目錄下多了兩個文件:

_cos_doubles.c,使用Python C-API自動包裝生成的C文件。

cos_doubles.pyx,Python可直接調用的module文件,也就是最終我們所需要的東西。

接下來測試一下:

# file: test.pynimport cos_doublesnimport numpy as npnimport matplotlib.pyplot as pltnna = np.linspace(-5, 5, 100)nb = np.empty_like(a)ncos_doubles.cos_doubles_func(a, b)nnplt.plot(b)nplt.shown()n

運行效果如下圖所示:

運行效果

參考資料

[1] SciPy lecture notes: 2.8. Interfacing with C

[2] Working with NumPy

[3] Python中使用C代碼:以NumPy為例

[4] Cython學習


推薦閱讀:

TAG:Python |