快速教程:使用Cython来扩展Python/NumPy库

前言

整个快速教程直接上例子,具体对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, Extensionimport numpyfrom 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学习

原文发布于微信公众号 - 人工智能LeadAI(atleadai)

原文发表时间:2017-12-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器学习和数学

[编程经验] Python中的modlue和packages的区别

今天聊一下,Python中模块和包的区别和联系,以及怎么创建自己的package,通过学习,你可以明白我们平时用Python的时候,到底import 了什么东西...

2413
来自专栏闻道于事

Linux-看完这篇Linux基本的操作就会了

993
来自专栏linux运维学习

linux学习第七篇:环境变量PATH,命令cp,mv以及文档查看cat,more,less,head,tail

环境变量PATH 变量说明: PATH这个变量包含了一系列由冒号分隔开的目录,系统就从这些目录里寻找可执行文件。如果你输入的可执行文件(例如ls、rm)不在这些...

1819
来自专栏Java与Android技术栈

Scala学习笔记(一)mac下安装ScalaIDE选择总结

过年前就定(chui)下了目(niu)标(bi),今年要学习一下Scala和Spark赶一下潮流。谁叫落后就要挨打呢,程序员只能不停的学习。一个语言,学习的第一...

632
来自专栏Golang语言社区

Go语言学习(一):hello world

每学一门语言,程序猿们总是不厌其烦地写一遍hello world,这篇就是Go语言的hello world。 Go语言的环境搭建建议参考《Go We...

3056
来自专栏hotqin888的专栏

EngineerCMS工程师知识管理系统支持项目模板

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/det...

783
来自专栏XAI

每一个程序员需要了解的10个Linux命令

以下就是今天我们要介绍的Linux命令:  man  touch, cat and less  sort and grep  cut  sed  tar  fi...

1816
来自专栏机器学习和数学

[编程经验]Python中os模块最最常用的方法

最近在搞天池的AI医疗那个比赛,所以没时间写文章了,有没有小伙伴想一起做的,可以找我私聊! ***********print("分割线")***********...

3185
来自专栏我的博客

apache 伪静态配置

今天想把一个文章发布系统改成伪静态,于是乎用了几个小时百度,google……找apache伪静态配置 一个网站基本上就三个简单的页面。index.php、li...

4275
来自专栏Python爬虫与数据挖掘

如何在交互式环境中执行Python程序

相信接触过Python的小伙伴们都知道运行Python脚本程序的方式有多种,目前主要的方式有:交互式环境运行、命令行窗口运行、开发工具上运行等,...

823

扫描关注云+社区