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. GridView Print and Print Preview

    sing System.Linq; using System.Printing; using System.Windows; using System.Windows.Controls; using ...

  2. 【java开发系列】—— 自定义注解

    之前在开发中,就总纳闷,为什么继承接口时,会出现@Override注解,有时候还会提示写注解@SuppressWarnings? 原来这是java特有的特性,注解! 那么什么是注解呢? 注解就是某种注 ...

  3. 关于Unity中混合模式、Alpha测试、深度测试、通道遮罩、面剔除的使用----渲染通道通用指令(二)

    混合模式 着色完成后,需要把颜色混合到帧缓冲区里面,涉及到源和目标. 1:在所有计算完成后,决定当前的计算结果输出到帧缓冲区时,如何混合源和目标,通常用来绘制半透明的物体;2: Blend Off 关 ...

  4. 【CUDA学习】内核程序调试

    调试工具 cuda-gdb,网上有英文版的说明文档. 其中大部分调试命令和gdb的调试命令相同. cuda程序分为主机端程序和设备端程序,主机端程序调试也就是C语言程序的调试 主要是设备端程序,关键点 ...

  5. android WiFi ASSOC_REJECT 流程跟踪

    Android设备在于AP关联时,如果AP返回关联拒绝帧,Android设别会把AP加入黑名单中. 黑名单中的设备将会在扫描时,延时一段时间放在后面处理. 代码以及log基于SDM450, Andro ...

  6. (转)FFmpeg源代码简单分析:avformat_find_stream_info()

    目录(?)[+] ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结 ...

  7. (转)ffmpeg资源一览

    一. FFmpeg主站1. FFmpeg的源码发布,资料网址:  http://www.ffmpeg.org/ 源代码镜像站点网址:https://github.com/FFmpeg/FFmpeg 2 ...

  8. IMP导入时的错误以及解决办法

    导出命令:exp 用户名/密码@localhost:5050/bkcyunty file=D:\bak\db.dmp log=D:\bak\db.log INDEXES=n STATISTICS=no ...

  9. js Object.prototype.toString.call()

    Object.prototype.toString.call(obj)使用方法以及原理   这几天看vue-router的源码 发现了Object.prototype.toString.call()这 ...

  10. sql 查找最后一条记录

    1.通过row select * from tablewhere rownum<(select count(*)+1 from table)minusselect * from tablewhe ...