专栏名称: Python开发者
人生苦短,我用 Python。伯乐在线旗下账号「Python开发者」分享 Python 相关的技术文章、工具资源、精选课程、热点资讯等。
目录
相关文章推荐
Python爱好者社区  ·  蔚来汽车裁员约10%,20分钟完成裁员。。。 ·  2 天前  
Python爱好者社区  ·  为什么it外包永远在招人? ·  昨天  
Python开发者  ·  13年后,AlexNet源代码终于公开:带注 ... ·  昨天  
Python爱好者社区  ·  无人报考!顶尖大学,校区关停 ·  4 天前  
Python爱好者社区  ·  卧槽,这就是最牛逼的python教程 ·  5 天前  
51好读  ›  专栏  ›  Python开发者

Python 通过 ctypes 调用 C 程序实例

Python开发者  · 公众号  · Python  · 2017-03-31 20:52

正文

(点击 上方蓝字 ,快速关注我们)


来源:思诚之道

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







请到「今天看啥」查看全文


推荐文章
Python爱好者社区  ·  蔚来汽车裁员约10%,20分钟完成裁员。。。
2 天前
Python爱好者社区  ·  为什么it外包永远在招人?
昨天
Python爱好者社区  ·  无人报考!顶尖大学,校区关停
4 天前
Python爱好者社区  ·  卧槽,这就是最牛逼的python教程
5 天前
刘晓博说楼市  ·  茶叶大数据告诉你:喝茶的重要性
8 年前
老子道德经  ·  目中有人才有路,心中有爱才有度
7 年前