前言
整個快速教程直接上例子,具體對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"
#include <math.h>
/* Compute the cosine of each element in in_array, storing the result in
* out_array. */
void cos_doubles(double * in_array, double * out_array, int size){
int i;
for(i=0;i<size;i++){
out_array[i] = cos(in_array[i]);
}
}
cos_doubles.h
#ifndef _COS_DOUBLES_H
#define _COS_DOUBLES_H
void cos_doubles(double * in_array, double * out_array, int size);
#endif
_cos_doubles.pyx
""" Example of wrapping a C function that takes C double arrays as input using
the Numpy declarations from Cython """
# import both numpy and the Cython declarations for numpy
import numpy as np
cimport numpy as np
# if you want to use the Numpy-C-API from Cython
# (not strictly necessary for this example)
np.import_array()
# cdefine the signature of our c function
cdef extern from "cos_doubles.h":
void cos_doubles (double * in_array, double * out_array, int size)
# create the wrapper code, with numpy type annotations
def cos_doubles_func(np.ndarray[double, ndim=1, mode="c"] in_array not None,
np.ndarray[double, ndim=1, mode="c"] out_array not None):
cos_doubles(<double*> np.PyArray_DATA(in_array),
<double*> np.PyArray_DATA(out_array),
in_array.shape[0])
setup.py
from distutils.core import setup, Extension
import numpy
from Cython.Distutils import build_ext
setup(
cmdclass={'build_ext': build_ext},
ext_modules=[Extension("cos_doubles",
sources=["_cos_doubles.pyx", "cos_doubles.c"],
include_dirs=[numpy.get_include()])],
)
編譯打包
在命令行窗口中進入到上述文件所在同級目錄,輸入:
>> 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.py
import cos_doubles
import numpy as np
import matplotlib.pyplot as plt
a = np.linspace(-5, 5, 100)
b = np.empty_like(a)
cos_doubles.cos_doubles_func(a, b)
plt.plot(b)
plt.show()
運行效果如下圖所示:
運行效果
參考資料
[1] SciPy lecture notes: 2.8. Interfacing with C
[2] Working with NumPy
[3] Python中使用C代碼:以NumPy為例
[4] Cython學習