Chapter2 :Compiling and Running Cython Code
编译运行Cython代码有好几种方式,没有必要全部掌握,可以根据需要选择合适的方式。这里例举了3种常见方式,基本也够用了。一般方法3创建setup.py是最基础的,自由度也最高
1. 使用Ipython进行cython函数的互动编译和使用,适合原型调试
2.使用pyximport可以直接import使用,import时会自动编译,使用比较方便。
#fib.pyx
import cython
def fib(int n):
cdef int i
cdef double a=0.0,b=1.0
for i in range(n):
a,b =a+b,a
return a
# main.py
import pyximport
pyximport.install()
import fib
res = fib.fib(90)
3.常规的编译方法,使用setuptool或distutils库。这种方式可以把cython部分代码编译成动态连接库,方便部署和源码的加密隐藏。
# setup.py
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize(["fib.pyx"],annotate=True)
)
执行下面命令,会生成一个fib*.so的动态链接库文件
python setup.py build_ext --inplace
'''
执行结果大致如下
running build_ext
building 'fib' extension
creating build
creating build/temp.linux-x86_64-3.8
gcc -pthread -B /home/a/miniconda3/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/a/miniconda3/include/python3.8 -c fib.c -o build/temp.linux-x86_64-3.8/fib.o
creating build/lib.linux-x86_64-3.8
gcc -pthread -shared -B /home/a/miniconda3/compiler_compat -L/home/a/miniconda3/lib -Wl,-rpath=/home/a/miniconda3/lib -Wl,--no-as-needed -Wl,--sysroot=/ build/temp.linux-x86_64-3.8/fib.o -o build/lib.linux-x86_64-3.8/fib.cpython-38-x86_64-linux-gnu.so
copying build/lib.linux-x86_64-3.8/fib.cpython-38-x86_64-linux-gnu.so ->
'''
# main.py
import fib
res = fib.fib(90)
Chapter3 :Cython in Depth
1.带有cdef的静态类型声明
# 声明方式1
cdef int i
cdef int j
cdef float k
j=0
i=j
k=12.0
j=2*k
assert i!=j
# 声明方式2
cdef int i,j,k
cdef float price,margin
# 声明方式3
cdef int i=0
cdef long int j=0,k=0
cdef float price=0.0,margin=1.0
# 其他cdef的表达式
#1)C指针
cdef int *p
cdef void **buf
#2)Stack-allocated C arrays(C数组)
cdef int arr[10]
cdef double points[20][30]
#3)其他可用类型
cdef size_t len
#4)结构体和集合
cdef tm time_struct
cdef int_short_union_t hi_log_bytes
#4)函数指针
cdef void (*f)(int,double)
2.Cython的自动类型推断(不推荐)
cimport cython
@cython.infer_types(True)
def more_inference():
i = 1
d = 2.0
c = 3+4*j
r = i*d +c
return r
3.Cython中的C指针
cdef double golden_ratio
cdef double *p_double
p_double = &golden_ratio
p_double[0] =1.618
print(golden_ratio)
# =>1.618
print(p_double[0])
# =>1.618
cython使用结构体用’.'访问,而不需要使用’->',在转成C语言时会自动转换
# C语言写法示例
cdef st_t *ps_t = make_struct()
cdef int a_doubled = ps_t->a+ps_t->a
#cython写法
cdef st_t *ps_t = make_struct()
cdef int a_doubled = ps_t.a+ps_t.a
4.静态和动态类型变量的混合
cdef list particles,modified_particles
cdef dict names_from_particles
cdef str pname
cdef set unique_particles
particles = list(names_from_particles.keys())
other_particles = particles
del other_particles[0]