正文
radius
=
3956.0
cdef
float
pi
=
3.14159265
cdef
float
x
=
pi
/
180.0
cdef
float
a
,
b
,
theta
,
c
a
=
(
90.0
-
lat1
)
*
(
x
)
b
=
(
90.0
-
lat2
)
*
(
x
)
theta
=
(
lon2
-
lon1
)
*
(
x
)
c
=
math
.
acos
((
math
.
cos
(
a
)
*
math
.
cos
(
b
))
+
(
math
.
sin
(
a
)
*
math
.
sin
(
b
)
*
math
.
cos
(
theta
)))
return
radius*
c
请注意,我们仍然importmath——cython让您在一定程度上混搭Python和C数据类型在。转换是自动的,但并非没有代价。在这个例子中我们所做的就是定义一个Python函数,声明它的输入参数是浮点数类型,并为所有变量声明类型为C浮点数据类型。计算部分它仍然使用了Python的 math 模块。
现在我们需要将其转换为C代码再编译为Python扩展。完成这一部的最好的办法是编写一个名为setup.py发布脚本。但是,现在我们用手工方式 ,以了解其中的巫术:
# this will create a c1.c file - the C source code to build a python extension
cython
c1
.
pyx
# Compile the object file
gcc
-
c
-
fPIC
-
I
/
usr
/
include
/
python2
.
5
/
c1
.
c
# Link it into a shared library
gcc
-
shared
c1
.
o
-
o
c1
.
so
现在你应该有一个c1.so(或.dll)文件,它可以被Python import。现在运行一下:
t
=
timeit
.
Timer
(
"c1.great_circle(%f,%f,%f,%f)"
%
(
lon1
,
lat1
,
lon2
,
lat2
),
"import c1"
)
print
"Cython function (still using python math)"
,
t
.
timeit
(
num
),
"sec"
约1.8秒 。并没有我们一开始期望的那种大大的性能提升。使用 python 的 math 模块应该是瓶颈。现在让我们使用C标准库替代之:
cdef extern
from
"math.h"
:
float
cosf
(
float
theta
)
float
sinf
(