0X00

ctypes 是强大的,使用它我们就能够调 用动态链接库中函数,同时创建各种复杂的 C 数据类型和底层操作函数。使得python也具备了底层内存操作的能力,再配合python本身强大的表达能力,这才知道为什么python是黑客必学的编程语言。

0x01  ctypes使用

ctypes 提供了三种方法调用动态链接库:cdll(), windll(), 和 oledll()。

它们的不同之处就在 于,函数的调用方法和返回值。cdll() 加载的库,其导出的函数必须使用标准的 cdecl 调用约定。

windll()方法加载的库,其导出的函数必须使用 stdcall 调用约定(Win32API 的原生约 定)。

oledll()方法和 windll()类似,不过如果函数返回一个 HRESULT 错误代码,可以使用 COM 函数得到具体的错误信息。

0X02  调用约定

调用约定专指函数的调用方法。其中包括,函数参数的传递方法,顺序(压入栈或 者传给寄存器),以及函数返回时,栈的平衡处理。

下面这两种约定是我们最常用到的: cdecl and stdcall。

cdecl 调用约定: 函数的参数从右往左依次压入栈内,函数的调用者, 在函数执行完成后,负责函数的平衡。这种约定常用于 x86 架构的 C 语言里。

In C

int  python_rocks(reason_one,reason_two,reason_three);

In x86 Assembly

push reason_three
push reason_two
push reason_one
call python_rocks
add esp,12

从上面的汇编代码中,可以清晰的看出参数的传递顺序,最后一行,栈指针增加了 12 个字节(三个参数传递个函数,每个被压入栈的指针都占 4 个字节,共 12

个), 使得 函数调用之后的栈指针恢复到调用前的位置。

stdcall调用约定:参数传递的顺序也是从右到左,不过栈的平衡处理由函数 my_socks 自己完成,而不是调用者。

In C

int my_socks(color_onecolor_two,color_three);

In x86 Assembly

push color_three
push color_two
push color_one
call my_socks

最后一点,这两种调用方式的返回值都存储在 EAX 中。

0x03 使用方法

Windows下:

from ctypes import *
msvcrt = cdll.msvcrt
msg = "Hello world!\n"
msvcrt.printf("Testing: %s", msg)

Linux下:

from ctypes import *
libc = CDLL("libc.so.6")
msg = "Hello, world!\n"
libc.printf("Testing: %s", msg)

使用 Python 创建一个 C数据类型很简单,可以很容易的使用由C或者C++些的组件。 下面这张图很好的表示了映射关系。

0x04 定义结构和联合

In C

union
{
long barley_long;
int barley_int;
char barley_char[8];
}barley_amount;

In Python 

class barley_amount(Union):
_fields_ = [
("barley_long", c_long),
("barley_int", c_int),
("barley_char", c_char * 8),
]

eg:

from ctypes import *
class barley_amount(Union):
_fields_ = [
("barley_long", c_long),
("barley_int", c_int),
("barley_char", c_char * 8),
]
value = raw_input("Enter the amount of barley to put into the beer vat:")
my_barley = barley_amount(int(value))
print "Barley amount as a long: %ld" % my_barley.barley_long
print "Barley amount as an int: %d" % my_barley.barley_int
print "Barley amount as a char: %s" % my_barley.barley_char

输出结果:

Enter the amount of barley to put into the beer vat:66
Barley amount as a long: 66
Barley amount as an int: 66
Barley amount as a char: B

给联合赋一个值就能得到三种不同的表现方式。最后一个 barley_char 输出的结果是 B, 因为 66 刚好是 B 的 ASCII 码。
barley_char 成员同时也是个数组,一个八个字符大小的数组。在 ctypes 中申请一个数组, 只要简单的将变量类型乘以想要申请的数量就可以了。

Python利用ctypes实现C库函数调用的更多相关文章

  1. Python利用ctypes实现按引用传参

    C的代码 void test_cref(char *a, int *b, char *data) { , sizeof(char)); strcpy(p, "cute"); a[] ...

  2. python利用or在列表解析中调用多个函数.py

    python利用or在列表解析中调用多个函数.py """ python利用or在列表解析中调用多个函数.py 2016年3月15日 05:08:42 codegay & ...

  3. 通过实例简介python使用ctypes模块调用C语言动态库

    看介绍python语言时,说它是胶水语言,可以调用其他语言.通过使用ctypes模块就可以调用C语言的动态库.下面先放上官方文档和几个比较好的博文. 1.官方文档:http://python.net/ ...

  4. [Python] 利用Django进行Web开发系列(二)

    1 编写第一个静态页面——Hello world页面 在上一篇博客<[Python] 利用Django进行Web开发系列(一)>中,我们创建了自己的目录mysite. Step1:创建视图 ...

  5. python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie)

    python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie) 主要包括两部分内容:(1)利用python中的dict实现Trie:(2) ...

  6. python 利用栈实现复杂计算器

    #第五周的作业--多功能计算器#1.实现加减乘除及括号的优先级的解析,不能使用eval功能,print(eval(equation))#2.解析复杂的计算,与真实的计算器结果一致#用户输入 1 - 2 ...

  7. Linux系统调用和库函数调用的区别

    Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions).系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用的意思 ...

  8. linux系统调用和库函数调用的区别(转)

    Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions).可以参考<Linux程序设计>(英文原版为<Beginning ...

  9. python 利用 ogr 写入shp文件,数据格式

    python 利用 ogr 写入 shp 文件, 定义shp文件中的属性字段(field)的数据格式为: OFTInteger # 整型 OFTIntegerList # 整型list OFTReal ...

随机推荐

  1. C#中指针的使用(转)

    在C#中,有时候希望通过指针来操作内存,这样可以提高效率.我们可以用unsafe关键字修饰含有指针操作的程序段,如下所示: class Program {   static int Main(stri ...

  2. idea 的git代码回退回某个版本

    intellij idea 的git代码回退回滚 找到Reset HEAD 填写提交码,注意这里要选择"hard" 使用命令行强制提交代码 git push -f

  3. Plugin [id: 'org.jetbrains.kotlin.jvm'] was not found in any of the following sources: gradle配置:kotlin("jvm")后报错

    本来打算兼容java和kotlin,可配置后,项目报错.查看之前项目 再打开当前报错项目: 很明显,报错的原因是jvm的运行文件没有加载进来,多次尝试无果... 只能重新搭建初始化项目了.

  4. Android连接远程数据库的避坑指南

    Android连接远程数据库的避坑指南 今天用Android Studio连接数据库时候,写了个测试连接的按钮,然后连接的时候报错了,报错信息: 2021-09-07 22:45:20.433 705 ...

  5. Kubernetes Pod 全面知识

    Pod 是在 Kubernetes 中创建和管理的.最小的可部署的计算单元,是最重要的对象之一.一个 Pod 中包含一个或多个容器,这些容器在 Pod 中能够共享网络.存储等环境. 学习 Kubern ...

  6. Python基础之流程控制for循环

    目录 1. 语法 2. for+break 3. for+continue 4. for循环嵌套 1. 语法 while循环可以对任何内容循环,但循环次数不可控 for循环基于容器类型的长度,循环次数 ...

  7. git添加新账号

    1,在linux上添加账号 useradd test passwd test usermod -G gitgroup  test  将test账号的组改为和git一样的组gitgroup  git所在 ...

  8. 学习java的第十天

    一.今日收获 1.java完全学习手册第二章2.9程序流程控制中的选择结构与顺序结构的例题 2.观看哔哩哔哩上的教学视频 二.今日问题 1.例题的问题不大,需要注意大小写,新的语句记忆不牢 2.哔哩哔 ...

  9. day12 form组件

    day12 form组件 今日内容 form组件前戏 form组件基本定义 form组件数据校验功能 form组件渲染标签 form组件提示信息 数据校验进阶 form组件补充 form组件源码探索 ...

  10. day03 部署NFS服务

    day03 部署NFS服务 NFS的原理 1.什么是NFS 共享网络文件存储服务器 2.NFS的原理 1.用户访问NFS客户端,将请求转化为函数 2.NFS通过TCP/IP连接服务端 3.NFS服务端 ...