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. autofac解析Mvc和Webapi的坑

    我们在项目中很早就开始使用autofac,也以为知道与mvc和webapi集成的做法. var builder = new ContainerBuilder(); // Mvc Register bu ...

  2. lua------------------Unity3D研究院编辑器之打开unity不可识别的文件(十三)

    Unity3D研究院编辑器之打开unity不可识别的文件(十三) 雨松MOMO [Unity3D拓展编辑器] 围观8597次 9 条评论 编辑日期:2017-03-02 字体:大 中 小   有些特殊 ...

  3. 系列篇:Python3.x那些事儿

    Python3.x那些事儿: http://jingyan.baidu.com/season/39306

  4. 【苏勇老师Linux 入门笔记】网络基础

    IP 地址 IP 编制时一个双层编制方案,一个 IP 地址标示一个主机 (或一个网卡接口). 一个 IP 地址分为两个部分:网络部分(所属区域)和主机部分(标示区域中的哪个主机).IPv4 共32位, ...

  5. json过滤某些属性 之@jsonignore

    Jackson相关: 使用Jackson相关的注解时一定要注意自己定义的属性命名是否规范. 命名不规范时会失去效果.(例如Ename ,Eage 为不规范命名.“nameE”,“ageE”为规范命名) ...

  6. js判断字符串是否json格式

    function isJSON(str) { if (typeof str == 'string') { try { var obj=JSON.parse(str); if(typeof obj == ...

  7. hive以文件创建表

    create table location( location string, ip string, name string, city string, classfication string, c ...

  8. 配置IDEA Scala环境

    http://snglw.blog.51cto.com/5832405/1634595

  9. ASP.NET获取文件名,后缀名

    using System.IO; //引入命名空间 string path = "text.aspx"; string pathName = Path.GetFileName(pa ...

  10. PHP上传原理及操作实现

    关于PHP上传文件的函数类库,网上有许多封装很完善,大家直接拿来用就可以. 本文章只是说下关于上传原理和简单的上传操作,老鸟就无视了哈^_^~ 还有一些安全性判断比如:服务端限制能接收图片类型的文件, ...