windll对象

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

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

2-1

对象名称

參数入栈顺序

清栈方式

返回值类型

cdll

从右向左

调用者

不固定

windll

从右向左

被调用者

不固定

oledll

从右向左

被调用者

WindowsError

 

windll对象

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

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

E:\Milang\python\Lib\ctypes

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

...

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)

...

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

MessageBox = windll.user32.MessageBoxW

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

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

windll.kernel32.GetModuleHandleW(None)

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

windll.gdi32

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

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

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

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

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

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

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

posted @ 2017-08-21 10:54  zhchoutai  阅读(1348)  评论(0编辑  收藏  举报