Linux红客的Python编程之道【PDF 源码】

作者:操作系统

那是本手册类的书籍,所以读书的时候不分明从头到尾。如若您是一个Python新手,提议把全书都旁观三遍,因为您会学到非常多须求的hack原理和编制程序技艺,便于将来的到位各样复杂的义务。假诺您早就对Python很熟习,而且对ctypes库也很掌握了,这就能够跳过第二章。当然,你也足以只是当当看里面感兴趣的一章,每章的代码都做了详尽的说明。

 1. 简介

        在python、java等语言中某个时候须求C做功用上的增加补充,在实际应用中,必要做一些数据的互动。因而就必要动用到链接库(动态库和静态库,注:这里只介绍动态库)。而本文首要介绍的是跨平台编写翻译:针对windows系统中的C 程序在linux编写翻译成动态链接库的进度。

行使 ctypes 模块组合 Python 程序和 C 程序
ctypes 模块
ctypes 是 Python 的二个正规模块,它涵盖在 Python2.3 及以上的本子里。ctypes 是三个 Python 的高端外界函数接口,它使得 Python 程序能够调用 C 语言编写翻译的静态链接库和动态链接库。运用 ctypes 模块,能够在 Python 源程序中开创,访谈和操作简捷的或复杂的 C 语言数据类型。最为重要的是 ctypes 模块能够在四个阳台上行事,包含Windows,Windows CE,Mac OS X,Linux,Solaris,FreeBSD,OpenBSD。
接下去通过多少个大致的例证来看一下 ctypes 模块怎么样构成 Python 程序和 C 程序。
源代码层面上的组成
运用 Python 本人提供的 ctypes 模块能够使 Python 语言和 C 语言在源代码层面上进展重组。本节介绍了怎样通过应用 ctypes 库,在 Python 程序中得以定义类似 C 语言的变量。
下表列出了 ctypes 变量类型,C 语言变量类型和 Python 语言变量类型之间的关联:
表 1. ctypes,c 语言和 Python 语言变量类型涉及

动用ctypes 的首先步正是知情怎么着分析和做客动态链接库中的函数。三个dynamicallylinked library(被动态连接的库)其实正是叁个二进制文件,可是貌似自身不运营,而是由别的程序调用实施。在Windows 上称作dynamic link libraries (DLL)动态链接库,在Linux 上称为shared objects (SO)分享库。无论怎么着平台,那些库中的函数都不能够不通过导出的名字调用,之后再在内部存款和储蓄器中寻觅真正的地点。所以符合规律境况下,要调用函数,都必须先深入分析出函数地址,可是ctypes 替我们实现了这一步。

 

2. .so及.dll介绍

图片 1

免费下载地址在

作者:Jerry Jho
链接:
来源:知乎
作品权归作者全数。商业转发请联系小编获得授权,非商业转发请评释出处。

2.1 .dll

      Windows下动态链接库以 .DLL 事实上和 EXE 文件一律,同属 PE 格式的进行文书。对于隐式的援用外界符号,需要把外界符号所在的岗位写在 PE 头上。PE 加载器将从 PE 头上找到正视的符号表,并加载正视的别样 DLL 文件。

     windows 能够存在二个dll 对另三个 dll 的隐式依赖。windows的这种dll机制在资深教科书《程序猿的小编修养》里留意分析过。windows搞的如此辛劳,其实正是思索到调用dll接口时的功用。

表1

用户名与密码都是www.linuxidc.com

摘要:模块ctypes是Python内建的用来调用动态链接库函数的成效模块,一定程度上能够用来Python与其余语言的插花编制程序。由于编写动态链接库,使用C/C 是最广大的措施,故ctypes最常用于Python与C/C 混合编制程序之中。

2.2 .so

     在Linix 下,.so 为分享库,是shared object,用于动态连接的(经常还以 lib 开首)。so 文件相当多为 elf 实践文件格式。当它们供给的外部符号,能够不写明这么些标志所在的地点。即一般so 文件并不知道它依赖的那么些符号在什么样 so 里面。那一个标识是由调用 dlopen 进程运维时提供的。dlopen 把这个标识通报给 dlopen 加载的 .so 文件,最后成就动态链接。

     Linix 下一般无需让 so和 so 有隐式倚重关系。效能方面linux也支撑另一种so机制,编写翻译so时不加 -fPIC 的,能够用内部存款和储蓄器空间换调用时间。

表 1 中的第一列是在 ctypes 库中定义的变量类型,第二列是 C 语言定义的变量类型,第三列是 Python 语言在不选取 ctypes 时定义的变量类型。
举例:
清单 1. ctypes 轻易利用

现实下载目录在 /二零一三年龄资历料/七月/十八日/Linux红客的Python编制程序之道【PDF 源码】/

=================================================================

2.3 .so和.dll相比较深入分析

    由于操作系统的两样,他们在众多下边恐怕不尽一样,上边从以下多少个地方举办演说。

(1) 动态库程序编写制定,在Windows系统下的实行文件格式是PE格式,动态库必要多个DllMain函数作为开首化的食指,平日在导出函数的扬言时索要有 _declspec(dllexport)关键字。Linux下的gcc编写翻译的推行文书暗许是ELF格式,不必要先导化入口,亦没有须求到函数做特别评释,编写相比较便利。

(2)动态库编写翻译,在windows系统下边,有有益的调度编写翻译处境,常常不用本人去编写makefile文件,但在linux下边,须要团结出手去编写makefile文件。

(3)动态库调用方面,Windows和Linux对其下编写制定的动态库都能够行使显式调用或隐式调用,但现实的调用方式也不尽同样。

(4) 动态库输出函数查看,在Windows中,有为数相当多工具和软件能够开始展览查看DLL中所输出的函数,比如命令行格局的dumpbin以及VC 工具中的 DEPENDS程序。在Linux系统中一般接纳nm来查阅输出函数,也可以选取ldd查看程序隐式链接的分享对象文件。

(5)对操作系统的借助,那三种动态库运营正视于个其余操作系统,不能够跨平台应用。因而,对于落到实处均等效果的动态库,必须为三种分裂的操作系统提供不相同的动态库版本。

>>> from ctypes import * # 导入 ctypes 库中所有模块
>>> i = c_int(45) # 定义一个 int 型变量,值为 45 
>>> i.value # 打印变量的值 45 
>>> i.value = 56 # 改变该变量的值为 56 
>>> i.value # 打印变量的新值 56

图片 2

1. ctypes 的规律以及优劣点

3. Linux下编译.so

从底下的例证能够更引人注目地看出 ctypes 里的变量类型和 C 语言变量类型的相似性:
清单 2. ctypes 使用 C 语言变量

从ctypes的文书档案中能够推论,在依次平台上均选用了对应平台动态加载动态链接库的法门,并由此一套花色映射的章程将Python与二进制动态链接库相连接。通过阅读ctypes自己的代码也能够证实那么些估算(/Modules/_ctypes/_ctypes.c和/Modules/_ctypes/callproc.c)。在Windows平台下,最后调用的是Windows API中LoadLibrary函数和GetProcAddress函数,在Linux和Mac OS X平台下,最后调用的是Posix规范中的dlopen和dlsym函数。ctypes 达成了一雨后春笋的类型转换方法,Python的数据类型会卷入或直接推算为C类型,作为函数的调用参数;函数的再次回到值也由此一多级的包裹成为Python类型。也正是说,PyObject* <-> C types的调换是由ctypes内部产生的,那和SWIG是同多个原理。

3.1  附加库 

     由于编译的是Windows上的C 代码,当中使用了附加的mysql、opencv及ffmpeg库,因而在Linux上海重机厂复编写翻译配置了相应版本的库。将相应编写翻译好的库下边lib和include路线记录下来在makefile中央银行使。

>>> p = create_string_buffer(10) # 定义一个可变字符串变量,长度为 10 
>>> p.raw # 初始值是全 0,即 C 语言中的字符串结束符’ \0 ’'x00x00x00x00x00x00x00x00x00x00' 
>>> p.value = "Student" # 字符串赋值 
>>> p.raw # 后三个字符仍是’ \0 ’'Studentx00x00x00' 
>>> p.value = "Big" # 再次赋值 
>>> p.raw # 只有前三个字符被修改,第四个字符被修改为’ \0 ’'Bigx00entx00x00x00'

从ctypes的贯彻原理轻便看出:

3.2  Linux下C/C 及附加库安装配备

1)安装C/C 编译器:

http://blog.csdn.net/qq_21460229/article/details/78650900

2)C/C 程序编写翻译 与 调节和测验

http://blog.csdn.net/haoel/article/details/2879

注:使用 ”-tui “ 选项能够将代码突显在文书用户分界面TUI。可用光标操控同时在底下的GDB shell中输入指令: $ gdb -tui [可实行程序名]

图片 3

3)安装eclipse进行C/C 开发

http://blog.csdn.net/dugujiujian1124/article/details/46801823

4)安装ffmpeg

https://my.oschina.net/u/1024107/blog/747807

5)安装opencv3.3

http://blog.csdn.net/bh451326803/article/details/79047875

6)安装mysql

http://blog.csdn.net/SmallTankPy/article/details/75451645

注:python导入mysql库:$ sudo yum install MySQL-python

上边例子表明了指针操作:
清单 3. ctypes 使用 C 语言指针

ctypes 有以下优点:

3.3  Makefile文件

Makefile是类unix境况下(举例Linux)的切近于批管理的"脚本"文件。其主导语法是: 目标 依赖 命令。Makefile 文件汇报了总体育工作程的编写翻译、连接等法则。有本身的书写格式、关键字、函数。像C 语言有谈得来的格式、关键字和函数同样。

1) 规则:

Makefile文件由一名目多数准则(rules)构成。每条法规的款型如下,下边第一行冒号前边的部分,叫做"目的"(target),冒号前边的有的称作"前置条件"(prerequisites);第二行必须由叁个tab键开头,后边跟着"命令"(commands)。

2)语法:

富含:注释、回声、通配符、形式相配、变量和赋值符、变量和赋值符、自动变量、决断和循环、函数等。

3)示例:

图片 4

>>> i = c_int(999) # 定义 int 类型变量 i,值为 999 
>>> pi = pointer(i) # 定义指针,指向变量 i 
>>> pi.contents # 打印指针所指的内容 c_long(999) 
>>> pi.contents = c_long(1000) # 通过指针改变变量 i 的值 
>>> pi.contents # 打印指针所指的内容 c_long(1000)
  • Python内建,无需单独安装
  • 能够平昔调用二进制的动态链接库
  • 在Python一侧,无需驾驭Python内部的劳作情势
  • 在C/C 一侧,也不须要明白Python内部的行事措施
  • 对主题类型的互动映射有优秀的支撑

3.4  注意的题目

    将windows下的C 代码放在linux上编译时除了有个别头文件导入路线稍作修改外还应该有一部分函数的修改如:

1)windows C 中的sprintf_s()  ->  Linux下的sprintf():

那就是说一箭双雕的方法是不仅可以在Windows的C 中编译也得以在linux上编写翻译的法子是:

在C 代码中投入定义:

#ifdef _WIN64

#define _CRT_SECURE_NO_WARNINGS

#endif

  1. windows C 中的_itoa_s()   -> Linux未定义:

我们得以应用sprintf()函数完毕该作用:

char buffer[20] 

 int n = 123456;  

sprintf(buffer,"%d",n);

上边例子表达了协会和数组的操作:
清单 4. ctypes 使用 C 语言数组和结构体

ctypes 有以下瑕玷:

4. 应用

>>> class POINT(Structure): # 定义一个结构,内含两个成员变量 x,y,均为 int 型 ... _fields_ = [("x", c_int), ... ("y", c_int)] ... 
>>> point = POINT(2,5)   # 定义一个 POINT 类型的变量,初始值为 x=2, y=5 
>>> print point.x, point.y # 打印变量 2 5 
>>> point = POINT(y=5)   # 重新定义一个 POINT 类型变量,x 取默认值 
>>> print point.x, point.y # 打印变量 0 5 
>>> POINT_ARRAY = POINT * 3 # 定义 POINT_ARRAY 为 POINT 的数组类型 # 定义一个 POINT 数组,内含三个 POINT 变量 
>>> pa = POINT_ARRAY(POINT(7, 7), POINT(8, 8), POINT(9, 9))     
>>> for p in pa: print p.x, p.y # 打印 POINT 数组中每个成员的值 ... 7 7 8 8 9 9
  • 平台包容性差
  • 不可能直接调用动态链接库中未经导出的函数或变量
  • 对C 的支撑差

4.1 python调用.so

     当需求采取调用c 的主次的时候,需求对原有的数量加叁个extern "C"封装一下就能够。采取g 编译的代码也亟需的,原因或者是因为c 编写翻译器编写翻译后的二进制so文件中,对c 的函数实行了重复的命名导致的。

Python 访问 C 语言 dll
透过 ctypes 模块,Python 程序可以访谈 C 语言编写翻译的 dll,本节通过叁个大约的例子,Python 程序 helloworld.py 中调用 some.dll 中的 helloworld 函数,来介绍 Python 程序怎么样调用 windows 平台上的 dll。
导入动态链接库清单 ctypes 导入 dll
from ctypes import windll # 首发轫入 ctypes 模块的 windll 子模块 somelibc = windll.LoadLibrary(some.dll) # 使用 windll 模块的 LoadLibrary 导入动态链接库
访谈动态链接库中的函数清单 ctypes 使用 dll 中的函数
somelibc. helloworld() # 那样就足以拿走 some.dll 的 helloworld 的再次回到值。

就个人的经验来看,ctypes 适合于“中轻量级”的Python C/C 混合编制程序。非常是境遇第三方库提供动态链接库和调用文书档案,且并未有编写翻译器或编写翻译器并不互般合营的场合下,使用ctypes特别便利。值得注意的是,对于某种需求,在Python自己就能够落成的情景下(举例获取系统时间、读写文件等),应该先行采纳Python本人的意义而毫无采纳操作系统提供的API接口,不然你的程序会丧失跨平台的性状。

4.2 ctypes库 

    ctypes使得python能够平素调用c语言开采的动态链接库,非常强劲。

为了选取ctypes,须依次完结以下步骤:

    * 编写动态连接库程序

    * 载入动态连接库

    * 将Python的指标转变为ctypes所能识其他参数

    * 使用ctypes的参数调用动态连接库中的函数

1)导入.so

import ctypes

so=ctypes.CDLL('/root/VideoCompute/libKeyFrame.so') 

so.get_hashfamily()

2) 数据类型

    ctypes 提供了某个原始C语言兼容的数据类型。第一列是在ctypes库中定义的变量类型,第二列是C定义的变量类型,第三列是Python在不使用ctypes时定义的变量类型。

图片 5

全方位 helloworld.py 是那般的:
清单 7. Python helloworld 代码

2. 二个轻松易行的例证

5. 总结

参谋连接:

https://blog.codingnow.com/2006/11/windows_unix_dynamic_library.html

http://blog.csdn.net/qq_15807167/article/details/53084267

from ctypes import windll def callc(): # load the some.dll 
somelibc = windll.LoadLibrary(some.dll) 
print somelibc. helloworld() 
if __name__== “__main__”: callc()

作为Python文书档案的一部分,ctypes 提供了完美的文书档案。但并未有Windows API编制程序经验的初学者读ctypes文书档案仍旧会晕头转向。这里举一个小例子,尽力避开Windows API以及POSIX本人的纷繁,读者只必要精晓C语言就可以。

在命令行运转 helloworld.py,在 console 上得以见到 some.dll 中 helloworld 的出口。
清单 8. Python hellpworld Windows command console 启动输出
C:>python C:pythontesthelloworld.py Hello World! Just a simple test.
Python 调用 C 语言 so
经过 ctypes 模块,Python 程序也足以访问 C 语言编写翻译的 so 文件。与 Python 调用 C 的 dll 的方法基本同样,本节通过贰个简易的例证,Python 程序 helloworld.py 中调用 some.so 中的 helloworld 函数,来介绍 Python 程序怎么着调用 linux 平台上的 so。
导入动态链接库清单 ctypes 导入 so
from ctypes import cdll # 首起头入 ctypes 模块的 cdll 子模块,注意 linux 平台上行使 cdll 的,并非 windll。

在品味本节例子从前,照旧要搭建Python扩大编制程序景况。见 搭建Python扩张开采情状 - 蛇之魅惑 - 今日头条专栏

somelibc = cdll.LoadLibrary(“./some.so”) # 使用 cdll 模块的 LoadLibrary 导入动态链接库

先是大家写七个C语言的小程序,然后把它编写翻译成动态链接库。

做客动态链接库中的函数清单 ctypes 使用 so 中的函数

//great_module.c
#include <nmmintrin.h>

#ifdef _MSC_VER
    #define DLL_EXPORT __declspec( dllexport ) 
#else
    #define DLL_EXPORT
#endif

DLL_EXPORT int great_function(unsigned int n) {
    return _mm_popcnt_u32(n);
}
somelibc. helloworld() # 使用方法与 windows 平台上是一样的。

其一源文件中独有三个函数 great_function,它会调用IntelSSE4.2指令集的POPCNT指令(封装在_mm_popcnt_u3第22中学),即计算三个无符号整数的二进制表示中“1”的个数。若是你的计算机是2009年前选购的,那么很或许不帮衬SSE4.2指令集,你只须求把return这一行改为 return n 1;就可以,同样能够表达难题。

整个 helloworld.py 是这么的:
清单 11. Python helloworld 代码

调用_mm_popcnt_u32需求包涵英特尔指令集头文件nmmintrin.h,它即使不是标准库的一有的,可是全数主流编译器都补助。

from ctypes import cdll def callc(): # load the some.so 
somelibc = cdll.LoadLibrary(some.so) print somelibc. helloworld() 
if __name__== “__main__”: callc()

中级还会有一坨#ifdef...#else...#endif,这一个是给MSVC计划的。因为在MSVC下,动态链接库导出的函数必须加 __declspec( dllexport ) 举办修饰。而gcc(Linux和Mac OS X的默许编写翻译器)下,全部函数默许均导出。

在命令行运维 helloworld.py,在 linux 规范输出上能够观察 some.so 中 helloworld 的出口。
清单 12. Python hellpworld Linux shell 周转输出

接下去把它编写翻译为动态链接库。Windows下动态链接库的扩张名是dll,Linux下是so,Mac OS X下是dylib。这里为了便利起见,一律将扩展名设定为dll。

[root@linux-790t] python ./helloworld.py Hello World! Just a simple test.

Windows MSVC 下编写翻译命令:(运营Visual Studio命令提醒)

Python 程序和 C 程序整合实例
以下我们例如用 Python 来兑现贰个小工具,用来贯彻 hash 算法,查看文件的校验和(MD5,CRC,SHA1 等等)。通过查看文件的校验和,能够精通文书在传输进度中是还是不是被破坏或歪曲。
Hash,一般翻译做“散列”,也会有平素音译为"哈希"的,便是把自由长度的输入(又叫做预映射,pre-image),通过散列算法,转变来固定长度的输出,该出口正是散列值。这种转移是一种压缩映射,也正是,散列值的长空常常远低于输入的半空中,差别的输入恐怕会散列成一样的输出,而不容许从散列值来独一的显明输入值。简来说之正是一种将随机长度的音信压缩到某一稳住长度的新闻摘要的函数。
是因为相对 C 语言来讲,Python 的运行效用非常低,因而大家的 Python 小工具利用三个已有的 C 语言的动态链接库 (hashtcalc.dll) 来贯彻大家的次第。本例中,大家应用 wxPython 编写轻便的 GUI 分界面,通过 python 调用 hashtcalc.dll 的接口总计文件的校验和,然后输出在分界面上。
架构图
图 1. 工具的架构图

cl /LD great_module.c /o great_module.dll 

图片 6

Windows GCC、Linux、Mac OS X下编译命令一样:

图 1. 工具的架构图

gcc -fPIC -shared -msse4.2 great_module.c -o great_module.dll

hashcalc.dll 接口描述
函数名:calc_CRC32
函数:char* calc_CRC32(char filename);
参数:文件名
返回值:字符串
评释:该函数对输入的文书内容开始展览计算,何况再次回到它的 CRC32
函数名:calc_MD5
函数:char
calc_MD5(char filename);
参数:文件名
返回值:字符串
注解:该函数对输入的文书内容张开总计,并且重返它的 MD5
函数名:calc_SHA1
函数:char
calc_SHA1 (char *filename);
参数:文件名
返回值:字符串
证实:该函数对输入的文书内容张开总括,况且再次回到它的 SHA1
HashcalcAdapter 代码
HashcalcAdapter.py 落成了二个 python 的 class HashcalcAdapter,HashcalcAdapter 对 hashtcalc.dl 的 C 语言接口举行了打包,使得其余 python 模块能够直接通过 HashcalcAdapter 使用 hashtcalc.dll 中实现的 hash 算法。具体的代码如下:
清单 13. HashcalcAdapter.py 代码

本文由ca88发布,转载请注明来源

关键词: ca88网址 yzc88亚洲城 Python 日记本