Python C++扩展

前置:准备工作

pip install cython

Cython模块包含将Py编译成C++的函数。

第一步:写Python代码

1
2
3
4
5
6
#example.pyx
def test(x):
y = 0
for i in range(x):
y += i
return y

用了非常简单的代码,将代码保存为.pyx 后缀。

第二步:写 setup.py

1
2
3
4
5
#setup.py
from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules=cythonize("example.pyx"))

将 setup.py 同example.pyx保存在同一个文件夹下,然后在cmd中执行:

python setup.py build_ext –inplace

此时文件夹下将会多出俩文件,分别是一个同名.pyd文件和同名.c文件。打开.c文件可以看到很多乱七八糟的东西,在c文件中搜索之后可以找到原来的py代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static int __pyx_f_10example_cy_test(int __pyx_v_x, CYTHON_UNUSED int __pyx_skip_dispatch) {
int __pyx_v_y;
int __pyx_v_i;
int __pyx_r;
__Pyx_RefNannyDeclarations
int __pyx_t_1;
int __pyx_t_2;
int __pyx_t_3;
__Pyx_RefNannySetupContext("test", 0);
__pyx_v_y = 0;
__pyx_t_1 = __pyx_v_x;
__pyx_t_2 = __pyx_t_1;

for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
__pyx_v_i = __pyx_t_3;
__pyx_v_y = (__pyx_v_y + __pyx_v_i);
}
__pyx_r = __pyx_v_y;
goto __pyx_L0;
__pyx_L0:;
__Pyx_RefNannyFinishContext();
return __pyx_r;
}

变这样了,确实怪里怪气的。

第三步:测试一下
现在已经可以用了,新创建一个py文件写测试代码

1
2
3
4
5
6
7
import timeit

cy = timeit.timeit('example_cy.test(5)', setup='import example_cy',number=100)
py = timeit.timeit('example_py.test(5)', setup='import example_py', number=100)

print(cy, py)
print('Cython is {}x faster'.format(py / cy))

example_cy是编译后的py文件,example_py是后缀为.py的文件。这个测试的内容是,同时执行example中的test函数,比较C编译后的执行比py执行快多少倍。
测试结果一般稳定在4~7倍,如果加大test传参,令其等于5000、50000,则相差的倍数会到惊人的120倍之多。

总结:(不一定对,这两天再看看
产生差异的原因(可能)是python动态语言的特性,比起C/C++来说少了基类型确定。
py: x=3
c: int x=3
多了个解释器的时间。