Linux/Unix 平台下共享库(Shared Library)文件后缀 .so;在 Windows 平台称为动态链接库(Dynamic Link Library),文件名后缀为 .dll。


利用 ctypes 模块调用 C 共享库

  ctypes 是 Python 标准库提供的一个模块,Python 2.3 版本以上支持该模块。ctypes 是 Python 高级外部函数接口,Python 通过它可以调用 C 语言编译的静态链接库和动态链接库。ctypes 支持多个平台,包括 Windows, Windows CE, Mac OS X, Linux, Solaris, FreeBSD, OpenBSD。

  ctypes 模块定义了一些基础 C 兼容数据类型,具体类型请点击此处查看。

  以下实例演示如何在 Python 程序中使用 ctypes 模块来调用 C 程序函数。

1. 准备 C 程序源文件 sum.c

  在 sum.c 源文件定义一个 sum() 函数,用以计算 N 个连续自然数之和。

#include <stdio.h>

int main(void){
int x;
printf("Input an integer:\n");
scanf("%d", &x);
printf("sum=%d\n", sum(x));
return ;
}; int sum(int x){
int i, result=;
for(i=; i<=x; i++){
result+=i;
}
return result;
};

2. 将 C 源代码编译成共享库文件 sum.so

  使用 gcc 编译器将 sum.c 编译为共享库文件 sum.so。

$ gcc sum.c -fPIC -shared -o sum.so

3. 准备 Python 模块 sum.py

  在 sum.py 模块中我们定义一个 py_sum() 函数,该函数是 sum.c 文件中 sum() 函数的 Python 实现。

#!/usr/bin/env python
# -*- coding: utf8 -*- import ctypes so = ctypes.CDLL('./sum.so') def display_dict():
print "Type of so is %s" % type(so)
print "Attributes before calling so.sum: %s" % dir(so)
print "so.sum(10) = %s" % so.sum(10)
print "Attributes after calling so.sum: %s" % dir(so) def py_sum(x):
y = 0
for i in range(x+1):
y += i
return y def so_sum(x):
return so.sum(x) if __name__ == "__main__":
pass

  在 Python 模块中 import ctypes,然后通过 ctypes.CDLL() 方法导入共享库文件 sum.so,之后就可以直接调用动态库提供的函数。

  

4. 测试 Python 调用共享库

  让我们在 __main__ 区块中调用 display_dict 函数:

if __name__ == "__main__":
display_dict()

  运行 sum.py 查看结果:

$ python sum.py
Type of so is <class 'ctypes.CDLL'>
Attributes before calling so.sum: ['_FuncPtr', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattr__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_func_flags_', '_func_restype_', '_handle', '_name']
so.sum() =
Attributes after calling so.sum: ['_FuncPtr', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattr__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_func_flags_', '_func_restype_', '_handle', '_name', 'sum']

  从结果可以发现 .so 共享库导入到 .py 模块中得到一个 ctypes.CDLL 对象。调用了 C 函数之后,CDLL 对象会将该函数添加到对象属性中。(在调用 sum 函数之后,CDLL 对象属性列表中才包含了 sum 函数。)

5. Python 调用共享库的性能

  我们修改一下 sum.py 模块:

if __name__ == "__main__":
import timeit
i =
print "py_sum(%s) = %s" % (i, py_sum(i))
print "so_sum(%s) = %s" % (i, so_sum(i)) print timeit.timeit("py_sum(10000)", setup="from __main__ import py_sum", number=)
print timeit.timeit("so_sum(10000)", setup="from __main__ import so_sum", number=)

  查看运行结果:

$ python sum.py
py_sum() =
so_sum() =
6.82061600685
0.158802986145

  以上测试显示,循环叠加 10000 次,执行代码 1000 次,Python 代码耗费了 6.820 秒,C 代码耗费了 0.158 秒,Python 代码耗费时间是 C 代码耗费时间的 42.95 倍。

[Python] Python 调用 C 共享库的更多相关文章

  1. 使用ctypes在Python中调用C++动态库

    使用ctypes在Python中调用C++动态库 入门操作 使用ctypes库可以直接调用C语言编写的动态库,而如果是调用C++编写的动态库,需要使用extern关键字对动态库的函数进行声明: #in ...

  2. go通过swig封装、调用c++共享库的技术总结

    go通过swig封装.调用c++共享库的技术总结 @(知识记录) 1 简介 最近在研究golang,希望能对目前既有的python服务做一些优化,这些服务目前已经占用了6-7台机器.选择golang的 ...

  3. android开发调用c++共享库so文件

    1.编写libaab.cpp #include <stdio.h>#include <stdlib.h> #ifdef __cplusplusextern "C&qu ...

  4. SQLite 版本引发的 Python 程序调用问题

    问题 在跑 OpenStack functional 功能测试的时候有两个用例过不去. nova.tests.functional.db.test_resource_provider.Resource ...

  5. QT共享库的创建与调用(初级)(附:UI界面不能被改变的其中一个原因)

    背景: 最近在做的一个项目其中一部分既是实现PC与下位机的USB通信.windows平台下已经完成,现需移植到linux平台下. 在linux系统中,通过一段时间的工作,设备已被配置成hid类(后续再 ...

  6. 【转载】Linux下动态共享库加载时的搜索路径详解

    转载自:http://www.eefocus.com/article/09-04/71617s.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loading ...

  7. Linux下动态共享库加载及使用详解【转】

    原文地址:http://blog.chinaunix.net/uid-29025972-id-3855500.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while l ...

  8. Linux下动态共享库加载时的搜索路径详解

    对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loading shared libraries”这样的错误,这是典型的因为需要的动态库不在动态链接器ld.so的搜索路径 ...

  9. Linux下动态共享库加载及使用详解

    转载;http://blog.chinaunix.net/uid-29025972-id-3855500.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loa ...

随机推荐

  1. [hbase] HBase内置过滤器的一些总结

    http://blog.csdn.net/cnweike/article/details/42920547

  2. Linux gcc/g++链接编译顺序详解

    gcc/g++链接时对库的顺序要求 -Ldir Add directory dir to the list of directories to be searched for -l. -llibrar ...

  3. == equals hashCode 总结比较

    在Java中: ==是运算符,用于比较两个变量是否相等. equals,是Objec类的方法,用于比较两个对象是否相等,默认Object类的equals方法是比较两个对象的地址,跟==的结果一样.Ob ...

  4. linux中怎么查看ip地址

    命令 ifconfig 可以查看当前主机的ip地址: 如果要手动更改ip地址. 可以输入命令cd /etc/sysconfig/network 在这个目录下会有 类似于ifcfg-@@的文件. 可以用 ...

  5. ubuntu安装mxnet GPU版本

    安装mxnet GPUsudo pip install mxnet-cu80==1.1.0 推荐pip安装mxnet,土豪gpu版本: pip install mxnet-cu90==1.0.0 豪华 ...

  6. Eclipse中配置resin 4.x

    开发web项目时,你还困扰在,反复启动web容器的痛苦中么?也许会有人说,用调试模式.但是如果涉及到配置文件或者service类,还是不得不重启web容器吧,而且偶尔会出现抽风情况,没生效的情况(这时 ...

  7. Spring系列(二):Spring IoC/DI的理解

    这几天重新学习了一下Spring,在网上找了相关的ppt来看,当看到Spring IoC这一章节的时候,先大致浏览了一下内容,有将近50页的内容,内心窃喜~QAQ~,看完这些内容能够对IoC有更深层次 ...

  8. 参考论坛:Mali kernel driver TX011-SW-99002-r5p1-00rel0 for firefly

    最近手头有一块firefly_rk3288_reload的开发板,想实现在linux 下用openGL ES来做视频显示. 找到opengGL相关移植,参考论坛(http://bbs.t-firefl ...

  9. (原)从mp4,flv文件中解析出h264和aac,送解码器解码失败

    转载请注明出处:http://www.cnblogs.com/lihaiping/p/5285166.html 今天在做本地文件解码测试,发现从mp4,flv文件中读出来的帧数据,h264和aac帧直 ...

  10. Fedora26 tftp-server设置

    安装tftp-server yum install -y  tftp-server 启动软件 systemctl start tftp.socket systemctl enable tftp.soc ...