(点击
上方蓝字
,快速关注我们)
来源:思诚之道
http://www.bjhee.com/python-ctypes.html
如有好文章投稿,请点击 → 这里了解详情
在做复杂计算时,Python的执行效率是无法同C比的。而且有些算法已经有开源的C库了,我们也没必要用Python重写一份。那Python怎么调用C语言写的程序库呢?答案就在Python提供的ctypes库,它提供同C语言兼容的数据类型,可以很方便地调用C语言动态链接库中的函数。
使用C标准库函数
我们来试试调用C标准库函数:
from
ctypes
import
cdll
libc
=
cdll
.
LoadLibrary
(
'libc.so.6'
)
# Load standard C library on Linux
# libc = cdll.LoadLibrary('libc.dylib') # Load standard C library on Mac
# libc = cdll.msvcrt # Load standard C library on Windows
print
libc
.
time
(
None
)
上述代码加载了Linux中的C标准库”libc.so.6″,并调用其中”time()”函数,执行后屏幕上会打印出当前时间戳。注,Windows和Mac上的加载方法在注释中。
调用自定义的动态链接库
我们先根据这篇文章(http://www.bjhee.com/java-native-1.html)写个动态链接库,现在你有了库”libhello.so”,其有一个hello函数。让我们在Python中调用它:
from
ctypes
import
cdll
libhello
=
cdll
.
LoadLibrary
(
"./libhello.so"
)
libhello
.
hello
(
'You'
)
看到屏幕上”Hello You!”的字样了吧。对!就这么简单,比起Java调用本地代码方便很多吧。注意,本例中的”libhello.so”同Python程序在同一目录下。
效率对比
我们写个阶乘(factorial)函数,来比较Python和C的执行效率吧。先写C代码:
int
factorial
(
int
n
)
{
if
(
n
2
)
return
1
;
return
factorial
(
n
-
1
)
*
n
;
}
方便起见,我们把它放在之前写的”hello.c”文件中,这样就可以从”libhello.so”中调用它。别忘了在”hello.h”中声明这个函数。然后实现Python代码:
def
factorial
(
n
)
:
if
n
2
:
return
1
return
factorial
(
n
-
1
)
*
n
def
factorial_c
(
n
)
:
return
libhello
.
factorial
(
n
)
Python的实现可以说同C的一模一样,我们另外定义一个”factorial_c()”函数来封装C的调用。现在,我们来比较下执行效率。这里要引入Python的”timeit”包,它可以帮你计算程序的执行时间,省去你很多代码。让我们来算20的阶乘,并计算10万次,看看所消耗的时间:
from
timeit
import
timeit
f_setup
=
'from __main__ import factorial'
f_c_setup
=
'from __main__ import factorial_c'
print
timeit
(
'factorial(20)'
,
setup
=
f_setup
,
number
=
100000
)
print
timeit
(
'factorial_c(20)'
,
setup
=
f_c_setup
,
number
=
100000
)
我在虚拟机上跑的结果结果是:
0.231598138809
0.0475780963898
差不多5倍的差距啊!
参数传址
大家知道C的函数参数是传值的(其实Python也一样),那我想在C中改变参数的值怎么办,那就需要传递引用了。我们在上面的”libhello.so”中加一个快排函数:
void quickSort
(
int
*
a
,
int
start
,
int
end
)
{
if
(
start
end
)
{
int
left
=
start
;
int
right
=
end
;
int
key
=
a
[
left
];
while
(
left
right
)
{
while
(
left
right
&&
a
[
right
]
>=
key
)
right
--
;
a
[
left
]
=
a
[
right
];
while