虽然Python简洁方便、深得人心,但用Python去实现(pip install无法解决时)某种处理大数据的算法,往往令人头疼。Python实现的代码往往是低效的,这时候需要C/C++来拯救。
本文介绍一种在Python中使用C/C++的方法。
首先,您需要Cython。
我们会把C/C++实现的算法打包成Python的扩展模块供Python代码调用。
创建目录algo
下面有4个文件
我们再倒过来逐一介绍
211#setup.py
2from distutils.core import setup, Extension
3from Cython.Build import cythonize
4
5import numpy as np
6
7extensions = [
8 Extension('algo', ['algo.pyx', 'algo_c.cpp'],
9 include_dirs = [np.get_include()],
10 language='c++',
11 include_dirs = [np.get_include(), 'some_path_to_include'],
12 library_dirs=['some_path_to_library'],
13 libraries=['some_name'],
14 extra_compile_args=["-std=c++11"],
15 extra_link_args=["-std=c++11"]),
16]
17#依次是 扩展模块的名称、 源文件(.pyx, .cpp)、 依赖的头文件地址(使用numpy则需添加np.get_include())、 语言(默认是C)、依赖的库(.so)地址、 依赖的库名称(e.g., for "libname.so", here is "name" not "lname")、 使用C++11标准、 使用C++11标准
18
19setup(
20 ext_modules = cythonize(extensions)
21)
191#algo.pyx
2from __future__ import division
3import numpy as np
4cimport numpy as np
5
6np.import_array()
7
8#引入需要的C/C++函数接口 (在algo_c.h中)
9cdef extern from "algo_c.h":
10 void some_function(float* arg0, int arg1, int arg2);
11
12cimport cython
13boundscheck(False) # turn off bounds-checking for entire function .
14wraparound(False) # turn off negative index wrapping for entire function .
15nonecheck(False) .
16
17#将引入的C/C++接口包裹成Python接口, 注意对numpy.ndarray的处理
18def some_function_func(np.ndarray[float, ndim=2, mode="c"] in_array0 not None):
19 some_function(<float*> np.PyArray_DATA(in_array0), in_array0.shape[0], in_array0.shape[1])
21//algo_c.h
2void some_function(float* arg0, int arg1, int arg2);
51//algo_c.cpp
2void some_function(float* arg0, int arg1, int arg2){
3 //... 函数的具体实现在此
4 return;
5}
在unix环境下通过
11python setup.py build_ext --inplace
生成可用的扩展模块,使用时
51#test.py
2import numpy as np
3from algo import some_function_func
4x = np.zeros([3,3],dtype=np.float32)
5some_function_func(x)
Reference