我的编程空间,编程开发者的网络收藏夹
学习永远不晚

厉害了,Python也能使用动态链接库

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

厉害了,Python也能使用动态链接库

一、神秘的模块

我们都知道C语言是比较靠近底层的语言,所以我们要想使用动态链接库就要给Python和C构建一座桥梁。今天我们要说的这座桥梁就是---Ctypes。

二、安装并导入Ctypes

系统自带有该模块,若没有,安装Pywin32也就有了。

from ctypes import *

三、认识动态链接库

动态链接库在linux 系统中表现为“.so”的后缀文件,而在Windows中表现为”.dll“的后缀文件。

四、初步了解Ctypes

安装好后我们需要对Ctypes做一个大致的了解,首先我们得先查看它的所有函数及其方法。

接下来我们就将对这些方法做一个简单的了解,并且配上一个小实例让大家看了之后更容易懂,让天底下不再有十分艰难的编程问题存在是我们的宗旨。

五、Ctypes的基本用法

1. 数据类型

Ctypes很完美的契合了C的数据类型,丰富多样,下面我们来看看吧:

我们可以看到这些都是可以在Python中使用的C语言数据类型。我们一起来看看它的用处吧:

我们可以看到这些基本就是数据类型的使用方法了,也是挺简单的。

2. 操作变量

刚刚我们定义了许多类型的变量,下面我们像使用C语言变量一样来使用它们。

(1) 访问变量的值

it.value

(2) 修改变量的值

it.value=43  #直接赋值,即可修改

(3) 给变量添加指针

#强指针
pt=pointer(it) pointer(c_int(10)) #定义指针,指向变量 pt,pt是指针内存地址
pt.contents #指针所指的对象
#弱指针 比强指针速度快
byref(it,4) #it:c的实例 4:偏移量
#返回一个指针的图片来做一个C实例,只可用作为函数参数

上面的指针只是简单的创建了指针实例,还有一种方法可以指定指针类型,然后进行创建:

aa=POINTER(c_int) #创建指针
aa(c_int(43)) #创建指针实例
aa(c_int(43)).contents.value#获取指针的值

也可以创建一个空指针:

POINTER(c_int)() #创建空指针,空指针是一个bool值

可以看出空指针没有Contents属性。

也可以使用抽象基类“_Pointer”来完成指针的操作:

import ctypes
class ss(ctypes._Pointer): #这里必须带上ctypes,否则会报错
_type_=c_int
contents=c_float
aa=ss(c_int(10)) #指定对象类型为整形
print(aa.contents) #替换为浮点类型

3. 创建修改缓冲

Ctypes定义的指针类型是不可以修改的,如果需要在C函数中被修改,需要使用一些函数来修改,下面来看看:

(1) 字符缓冲

p=create_string_buffer(4)           #创建一个4字节缓冲区 初始化为空字节
create_string_buffer(b"Hello") #创建一个包含空字符结尾字符串缓冲区
create_string_buffer(b"Hello", 10) #创建一个10字节缓冲区
print(sizeof(p),repr(p.raw)) #内存块大小 字节信息

(2) unicode缓冲

a=create_unicode_buffer(5)  #创建一个10字节的unicode字符缓冲区
create_unicode_buffer('ffsa')
create_unicode_buffer('ffsa',5) #结尾空字符
print(sizeof(a)) #内存块大小

4. 调用动态链接库

动态链接库的调用方法很多,任你挑选。

CDLL(xx.dll)
OleDLL(xx.dll)
PyDLL(xx.dll)
WinDLL(xx.dll)
cdll.LoadLibrary(xx.dll)
oledll.LoadLibrary(xx.dll)
pydll.LoadLibrary(xx.dll)
windll.LoadLibrary(xx.dll)
#也可使用链接库读取器LibraryLoader,它也同样支持上面的八种方式
LibraryLoader(CDLL('C:\\Windows\\System32\\user32.dll'))
LibraryLoader(cdll.LoadLibrary('C:\\Windows\\System32\\user32.dll'))

综上所述,调用动态链接库的方法共有16种之多。

5. 查找动态链接库

from ctypes.util import find_library
find_library('user32')# 查找

6. 调用动态链接库函数

dll=windll.LoadLibrary(xx.dll)
dll.函数名

7. Windows Api函数

所有的Window Api 函数都包含在Dll中,其中有几个非常重要的Dll:

kernel32.dll    #用于管理内存、进程和线程的各个函数
user32.dll #用于创建用户界面的各个函数
gdi32.dll #用于画图和显示文本的各个函数
advapi32.dll #用于操作注册表、系统终止与重启、Windows服务启动/停止/创建、账户管理的各个函数
shell32.dll #用于访问操作系统shell提供的功能
netapi32.dll #用于访问操作系统提供的各种通信功能
comctl32.dll #用于访问操作系统的状态条、进度条、工具条等功能
comdlg32.dll #用于管理文件打开、文件保存、颜色字体选择等标准对话框

#调用这些dll非常简单:
windll.gdi32 #即可

8. 获取模块头

windll.kernel32#同时导出同一个函数的ANSI版本(GetModuleHandleA)和UNICODE版(GetModuleHandleW)
windll.kernel32.GetModuleHandleA(0) #里面只允许有0或者None,其它会报错
windll.kernel32.GetModuleHandleW()

9. Dll基本信息获取

当我们读取Dll后有时候需要对它的路径或者句柄进行操作,这个时候我们需要获取这些参数:

(1) 获取窗口句柄

dll._handle

(2) 获取Dll绝对路径

dll._name

10. 调用Python中的Os模块中的所有方法

这个自是不必说,与Os模块密切相关。

os=ctypes._os
os.getcwd()

11. 打印字符长度

windll.msvcrt.printf(b'fsfs') #不支持中文输出 输出为4
windll.msvcrt.printf('fsfs') #输出为2
#以下情况与上相同
cdll.msvcrt.printf('fsfs')
pydll.msvcrt.printf('fsfs')
oledll.msvcrt.printf('fsfs')

12. 获取C实例内部缓冲区地址

addressof(c_int(30))

13. 判断是否有管理员权限

windll.shell32.IsUserAnAdmin()
cdll.shell32.IsUserAnAdmin()
pydll.shell32.IsUserAnAdmin()
oledll.shell32.IsUserAnAdmin()
#结果返回1则表示有,否则无

通过判断当前用户是否为管理员用户后,我可以进行下一步操作,如果是则打开浏览器,如果不是则尝试打开:

import ctypes, sys
def admin():
try:
aa=ctypes.windll.shell32.IsUserAnAdmin()
except:
return
finally:
return aa
if admin()==1:
os.popen(r'E:\360browser\360se6\Application\360se.exe')
else:
if sys.version_info[0] == 3:
ctypes.windll.shell32.ShellExecuteW(0, "runas", sys.executable,'',__file__,0)
else:
print('版本太低,不支持2.0')

#sys.executable:python主程序的绝对路径
#__file__:当前程序的绝对路径

14. 让鼠标键盘失灵

aa=cdll.LoadLibrary('C:\\Windows\\System32\\user32.dll')
aa.BlockInput(True)#键盘鼠标被锁定
time.sleep(5) # 锁定五秒
aa.BlockInput(False) #被释放

15. 打开文件或者应用程序

aa=windll.shell32.ShellExecuteW(0,'open','C:\\Windows\\System32\\notepad.exe','',os.path.join(os.path.dirname(__file__),'OSI.txt'),0)
#参数1:父窗口的句柄,如果没有父窗口,则为0
#参数2:要运行的操作,如:runas,open,print
#参数3:要运行的程序绝对路径
#参数4:给程序传递的参数,如果打开的是文件则为空
#参数5:要打开的文件的绝对路径
#参数6:是否显示窗口 0:后台打开 1:前台打开
#如果aa返回值小于32则表示打开失败
aa.bit_length()#指定数值的二进制的长度数、宽度数

16. 结构体和联合体

要想使用必须从Structure 和 Union 继承,子类必须定义,Fields 属性,Fields属性必须是一个二元组的列表。

元祖中第一个是变量名,第二个是数据类型,可以是Ctypes任意一种变量类型。

(1) 结构体Structure

也可以一次性传递多个不同数据类型的参数:

(2) 联合体Union

它和结构体的使用方法一样,但是结果不同,下面我们来看下:

造成这一区别的原因联合体所有成员变量共用一块内存,可以内存复用;而结构体,每个成员变量占用一块内存。

17. 数组操作

ARRAY(type,len) #前者是Ctypes的某个类型的值,而后者是值的长度,返回一个值与长度的乘积
Array(*args) #它是一个数组抽象基类, 我们可以重写它来进行使用,
class cx(Array):
_length_=100 #重写方法_length_(数组中元素的数量)
_type_=c_int #指定数组中每个元素的类型(整形)
aa=cx(12,32,43,324,54,4,32,34,52434)
print(aa[2],aa[5:7]) #利用下标或者切片访问

18. 改变对象的内存缓冲区大小

Ctypes可以重新设置对象的内存缓冲区大小:

可以看到,此时的同一个对象内存缓冲区大小不一样.

19. 转换指向不同数据类型的指针

这里我们用到了一个神器的函数“Cast”,它可以将不同的数据类型的指针进行转换。

class bb(Structure):
_fields_ = [("val", POINTER(c_int))]
b=bb()
b.val=cast((c_float*4)(1.2,3.2,4.3),POINTER(c_int))
print(b.val[1])

20. 进程操作

aa=0x00000020 #定义正常优先级的类
ker=windll.LoadLibrary('kernel32.dll') #加载动态链接库
crk=ker.CreateProcessA #获得创建后的进程的函数地址
rk=ker.ReadProcessMemory #获得读取进程内存的函数地址
wk=ker.WriteProcessMemory #获得写入进程内存的函数地址
ker.TerminateProcess #终止进程
print(ker,'\n',crk,'\n',rk,'\n',wk)

21. 调用Window系统Api

就以Window 弹框函数MessageBox为例。

from ctypes import c_int, WINFUNCTYPE, windll
from ctypes.wintypes import HWND, LPCWSTR, UINT
tp = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT) #window函数类型
bt = (1, "hwnd", 0), (1, "text", "我是内容"), (1, "caption", "我是"), (1, "type", 0)
MessageBox =tp(("MessageBoxW", windll.user32),bt) #调用消息弹框函数
MessageBox()
ab=MessageBox(caption='提示',text="我也是内容") #设置弹框参数
aa=MessageBox(caption='警告',type=2,text="是否进入?")
if aa==3: #判断输出类型
print('终止操作')
if aa==4:
print('重试')
if aa==5:
print('忽略')

可以看到当我选择了中止之后它便提示终止操作。其实还有一种类似的方法:

注:这里弹窗的参数均不支持中文,务必按我上面的格式写,不然会出错。

22. 获取Windows窗口中的所有顶层窗口的值


from ctypes import *
from ctypes import wintypes
#定义回调函数类型
res= WINFUNCTYPE(wintypes.BOOL,wintypes.HWND, wintypes.LPARAM)
def win(h,p):#实现回调函数功能,函数为bool类型;h:顶层窗口的句柄 p:应用程序定义的一个值,
le= user32.GetWindowTextLengthW(h)+1 #获取window文本长度,加1可获取完整的信息
buffer = create_unicode_buffer(le) #创建缓冲
user32.GetWindowTextW(h, buffer, le) #获取window文本
print(buffer.value) #获取缓冲区中的信息
return True
user32 = windll.LoadLibrary('user32.dll')#加载dll
user32.EnumWindows(res(win), 0) #枚举顶层窗口,不列举子窗口

六、总结

Ctypes总的来说还是蛮不错的,挺适合C语言小白学习,毕竟Api的确太多太复杂了,还是Python友好点。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

厉害了,Python也能使用动态链接库

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

厉害了,Python也能使用动态链接库

Ctypes总的来说还是蛮不错的,挺适合C语言小白学习,毕竟Api的确太多太复杂了,还是Python友好点。

python调用dll动态链接库

还是调用动态库,各种调用,但是呢,Python调用dll貌似不麻烦,至少我第一次就调用成功嘞。至于Python,我连语法都不知道,不过问题不大,边百度边写。环境:好像都可以,Python我在官网下载的python-3.6.4-amd64。然
2023-01-31

Linux动态链接库的使用

动态链接库与普通的程序相比而言,没有main函数,是一系列函数的实现。通过shared和fPIC编译参数生产so动态链接库文件。程序在调用库函数时,只需要连接上这个库即可。例如下面实现一个简单的整数四则运输的动态链接库,定义的caculat
2022-06-04

python调用动态链接库传送proto

什么是protobuf   protobuf是Google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,其最大的特点是基于二进制,因此比传统的XML表示高效短小得多。开发者定义类似于结构体的message,通过prot
2023-01-31

linux动态链接库的使用方法

这篇文章主要介绍“linux动态链接库的使用方法”,在日常操作中,相信很多人在linux动态链接库的使用方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”linux动态链接库的使用方法”的疑惑有所帮助!接下来
2023-06-09

linux动态链接库使用方法分享

1、前言 在实际开发过程中,各个模块之间会涉及到一些通用的功能,比如读写文件,查找、排序。为了减少代码的冗余,提高代码的质量,可以将这些通用的部分提取出来,做出公共的模块库。通过动态链接库可以实现多个模块之间共享公共的函数。之前看《程序员的
2022-06-04

怎么使用C/C++生成的动态链接库

这篇文章主要讲解了“怎么使用C/C++生成的动态链接库”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用C/C++生成的动态链接库”吧!操作环境:Visual Studio 2017.N
2023-06-26

ubuntu中python调用C/C++方法之动态链接库详解

安装booJlLUslVOSstpython调用C/C++的方法有很多,本文使用boost.python。考虑到后期有好多在boost上的开发工作,所以boost一并安装了,Boost库分为两个部分来使用,一是直接使用对应的头文件,二是需要
2022-06-04

解密 Python 如何调用 Rust 编译生成的动态链接库

我们就介绍了 Python 如何调用 Rust 编译的动态库,再次强调一下,通过 ctypes 调用动态库是最方便、最简单的方式。它和 Python 的版本无关,也不涉及底层的 C 扩展,它只是将 Rust 编译成 C ABI 兼容的动态库
PythonRust2024-11-30

Win7运行某软件提示无法定位动态链接库导致软件无法使用

Win7运行某软件时提示编程无法定位动态链接库user32.dll怎么办?当我们在win7系统上面运行软件的过程中有时候会总是提示说无法定位程序输入点dwmhintdxupdate于动态链python接库user32.dll上,导致这个软件
2023-06-06

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录