回过头来,再看一下windll和oledll的差别,这两者之间最大的差别是oledll调用的函数都是固定返回HRESULT类型的值,而windll是不固定的类型的。在Python 3.3版本号之前,都是返回命名为OSError类型错误,在这之后就返回命名为WindowsError类型错误。

通一大段的讨论,我们彻底地了解cdll、windll和oledll之间的差别。为了更加清晰地记住它们,总结例如以下表所看到的:

表2-1:

对象名称

參数入栈顺序

清栈方式

返回值类型

cdll

从右向左

调用者

不固定

windll

从右向左

被调用者

不固定

oledll

从右向左

被调用者

WindowsError

windll对象

调用WIN32的API函数,主要是通过windll对象来实现。那windll是何许人也?因为Python是开源的项目,我们非常方便就定位到它的源代码库里,查看它的实现方式。这样对于了解windll背后的秘密带来了极大的方便,假设是商业的项目就比較艰难了。

在Milang或者Python的安装文件夹下,例如以下:

E:\Milang\python\Lib\ctypes

就能够找到ctypes库,这个库是通过包来公布的,因此在此文件夹下看到__init__.py文件。这个文件就是ctypes库导入时最初执行的文件,那么cdll、windll和oledll对象就是在这里创建的。与这里讨论相关的代码例如以下:

...

cdll = LibraryLoader(CDLL)

pydll = LibraryLoader(PyDLL)

if _os.name in ("nt", "ce"):

pythonapi = PyDLL("python dll", None, _sys.dllhandle)

elif _sys.platform == "cygwin":

pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])

else:

pythonapi = PyDLL(None)

if _os.name in ("nt", "ce"):

windll = LibraryLoader(WinDLL)

oledll = LibraryLoader(OleDLL)

...

通过这段代码能够看到,windll是LibraryLoader类的实例,它是一个WinDLL类型的对象。LibraryLoader的主要功能就是实现动态库连接库的搜索、载入和重载运算符。让在Python里使用动态连接库更加方便。到这里就能够来看这句代码的详细意思了:

MessageBox = windll.user32.MessageBoxW

windll就是前面创建的动态连接库载入对象,user32是Windows提供的WIN32的API接口的动态连接库的名称(user32.dll)。MessageBoxW是WIN32提供的弹出一个提示框的函数名称。在这行代码里。有意思的是并没有採用传送參数的方式来訪问不同的动态连接库。而通过属性的方式(点号执行)来选择不同的动态连接库。

在这里.user32就是表示訪问动态连接user32.dll。像以下这行代码:

windll.kernel32.GetModuleHandleW(None)

就是表示訪问动态连接库kernel32.dll,因此訪问动态连接库gdi32.dll,就是变成这样:

windll.gdi32

通过点号运算就能够方便地载入不同的动态连接库。这是因为LibraryLoader类在后面进行点号运算符进行重载的结果。这样使用起来更方便和更清晰,比传送參数打更少的代码。在Windows里主要提供以下三个动态连接来对Windows的功能调用。例如以下:

kernel32.dll是Windows9x/Me中非常重要的32位动态链接库文件,属于内核级文件。它控制着系统的内存管理、数据的输入输出操作和中断处理,当Windows启动时,kernel32.dll就驻留在内存中特定的写保护区域,使别的程序无法占用这个内存区域。

user32.dll是Windows用户界面相关应用程序接口,用于包括Windows处理,基本用户界面等特性,如创建窗体和发送消息。

gdi32.dll是Windows GDI图形用户界面相关程序,包括的函数用来绘制图像和显示文字。

在这里有一点,你或许注意到了。当想调用MessageBox函数时,事实上是写的名称是MessageBoxW。在后面多了一个W。这个W是什么用的呢?事实上在WIN32的API里,提供了两套的API接口,一套是支持是UNICODE的API接口,一套是支持ANSI的API接口。说白了就是为了解决双字节和单字节的文字的显示问题。

因此,要想使用ANSI单字的API接口,要使用MessageBoxA的名称。

在我们编写C和C++程序时。仅仅须要使用MessageBox就能够了。事实上这是因为API在接口的头文件进行宏定义。在Python里没有必要进行这样的魔幻的操作,让人更加明了,明确。

windll对象的更多相关文章

  1. from声明

    在整个应用程序,只有三行声明.这是最短单WIN32应用,但它的功能是非常有限,简单地显示一个消息框,示出来,其他什么事情也没有做.以下就来分析这三行语句了.别小看这三行语句.其实是隐藏着非常多知识点在 ...

  2. cdll和windll的差别

    Python要想调用C语言写的动态连接库.不仅要兼容C接口的调用习惯,还须要兼容C语言的数据类型.幸运的是ctypes库已经做了这双方面的工作.以便调用动态连接库是很方便的.在Hello World的 ...

  3. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  4. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  5. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  6. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

  7. JS核心系列:浅谈原型对象和原型链

    在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象(Object)和函数对象(Function). 一般而言,通过new Function产生的对象是函数对象,其他对 ...

  8. Chrome出了个小bug:论如何在Chrome下劫持原生只读对象

    Chrome出了个小bug:论如何在Chrome下劫持原生只读对象 概述 众所周知,虽然JavaScript是个很灵活的语言,浏览器里很多原生的方法都可以随意覆盖或者重写,比如alert.但是为了保证 ...

  9. XStream将java对象转换为xml时,对象字段中的下划线“_”,转换后变成了两个的解决办法

            在前几天的一个项目中,由于数据库字段的命名原因 其中有两项:一项叫做"市场价格"一项叫做"商店价格" 为了便于区分,遂分别将其命名为market ...

随机推荐

  1. Day5上午解题报告

    预计分数:100+40+30=170 实际假分数:0+0+0=0 CE*3 实际真分数:60+50+0=110 老师没把我的程序放的文件夹里面,于是..... T1 https://www.luogu ...

  2. Manning.EJB.3.in.Action.2nd.Edition

    Manning.EJB.3.in.Action.2nd.Edition http://files.cnblogs.com/files/rojas/EJB_3_in_Action_2nd_Edition ...

  3. Codeforces Round #194 (Div. 2) 部分题解

    http://codeforces.com/contest/334 A题意:1-n^2 平均分成 n 份,每份n个数,且和相同 解法 : 构造矩阵1-n^2的矩阵即可 ][]; int main() ...

  4. Netty推荐addListener回调异步执行

    说明 Netty推荐使用addListener的方式来回调异步执行的结果,这种方式优于Future.get,能够更精确地把握异步执行结束的时间. 错误理解使用addListener的方式 代码如下: ...

  5. ORA-16014 ORA-00312

    打开alert日志发现如下错误信息 Errors in file /oracle/app/oracle/admin/hncdfhq/bdump/hncdfhq_arc0_45285882.trc: O ...

  6. 软件——protel 的pcb电路图制作

    近期一直在学习PCB板的绘制.

  7. 【部分原创】python实现视频内的face swap(换脸)

    1.准备工作,按博主的环境为准 Python 3.5 Opencv 3 Tensorflow 1.3.1 Keras 2 cudnn和CUDA,如果你的GPU足够厉害并且支持的话,可以选择安装 那就先 ...

  8. Altium Designer中死铜的问题

  9. J实现时间格式的转换(附加对象的转换)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. UIDeviceOrientationDidChangeNotification和UIApplicationDidChangeStatusBarFrameNotification

    这几天做App的时候,需要添加旋转屏通知以便调整UI布局 刚开始我使用的是UIDeviceOrientationDidChangeNotification, 一直有一些问题就是,如果使用这个通知,当i ...