Python的扩展接口[2] -> 动态链接库DLL[1] -> 组件对象模型 COM 的 Python 调用
关于COM的基本概念,可参考组件对象模型 COM 的内容,下面主要介绍两种使用 Python 调用 COM 组件的方法。
1 使用 win32com
1.1 环境搭建
首先需要搭建Python的环境,需要安装win32com包,前往下载对应版本的安装包。
Note: 值得注意的是,若COM组件是32位的,则需要下载32位的Python和包,64位则下载64位对应包。
1.2 导出中间层py文件
在确保COM组件注册的情况下,需要使用win32com提供的工具makepy.py来生成一个Python的中间层。使用方法参考链接,
主要步骤如下,
1. cd到makepy.py所在目录,一般为C:\Python3x\Lib\site-packages\win32com\client下;
2. 执行命令python makepy.py[ -o],其中括号内参数可以查看makepy.py文件内部说明;
3. 此时会弹出一个窗口,用于选择需要转换的控件;
4. 选择完毕后会显示如下提示,找到提示目录下的py文件,可以打开查看;
5. py接口文件中会显示一些基本信息,以及内部的接口函数,
转换后的中间层文件完整代码如下,
View Code
其中,从Py接口文件头部信息部分代码中可以查看到基本信息,以及一些重要参数(CLSID/LCID/Major/Minor等)。
1 # -*- coding: mbcs -*- 2 # Created by makepy.py version 0.5.01 3 # By python version 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit (Intel)] 4 # From type library 'RuMasterLib.tlb' 5 # On Thu Oct 12 22:28:05 2017 6 'RU Master 2.20 Type Library' 7 makepy_version = '0.5.01' 8 python_version = 0x30404f0 9 10 import win32com.client.CLSIDToClass, pythoncom, pywintypes 11 import win32com.client.util 12 from pywintypes import IID 13 from win32com.client import Dispatch 14 15 # The following 3 lines may need tweaking for the particular server 16 # Candidates are pythoncom.Missing, .Empty and .ArgNotFound 17 defaultNamedOptArg=pythoncom.Empty 18 defaultNamedNotOptArg=pythoncom.Empty 19 defaultUnnamedArg=pythoncom.Empty 20 21 CLSID = IID('{2C485B34-1437-4F59-8128-C387F8E8147B}') 22 MajorVersion = 1 23 MinorVersion = 0 24 LibraryFlags = 8 25 LCID = 0x0
而Py接口文件的最后一个类(基类为CoClassBaseClass),通常包含则真正调用的dll文件的信息,同时也是最终使用的dll文件的类对象。
可以看到,这个类的CLSID与对应的COM/DLL文件的CLSID(可通过OleViewer查看)是相同的,同时也可以看到这个类的名称(RuMaster.RuControl)。
1 from win32com.client import CoClassBaseClass 2 # This CoClass is known by the name 'RuMaster.RuControl' 3 class RuControl(CoClassBaseClass): # A CoClass 4 # RuControl Class 5 CLSID = IID('{75BF5D19-5AB0-4004-97EE-F039164681A3}') 6 coclass_sources = [ 7 ] 8 coclass_interfaces = [ 9 IRuControl3, 10 IRuControl1, 11 IRuControl4, 12 IRuControl2, 13 _Object, 14 ] 15 default_interface = IRuControl4
1.3 生成COM组件对象实例
到目前为止已经生成了一个中间层用于与COM/DLL进行交互,此时利用代码将这个中间层导入并生成对象实例来使用它。
完整代码
View Code
分段分析
首先导入win32com的client模块,
1 from win32com import client
此时有两种方式进行组件的实例化,第一种是利用中间层,即通过makepy生成的接口文件来实例化,具体方式如下,利用文件中提供的参数(CLSID/LCID/Major/Minor),按顺序传入函数中,此时生成的实例实际上是由中间层接口得到的。再利用这个中间层实例得到所需要使用的dll文件的实例(实际上此处完成的也是利用dll文件的id码生成实例)。
1 interface = client.gencache.EnsureModule("{2C485B34-1437-4F59-8128-C387F8E8147B}", 0x0, 1, 0) 2 3 # interface.RuControl: <class 'win32com.gen_py.2C485B34-1437-4F59-8128-C387F8E8147Bx0x1x0.RuControl'> 4 ru_control = interface.RuControl()
当然,也可以绕开上面的中间直接生成所需要的实例,即通过COM组件的dll文件本身的CLSID/UUID码或注册名称来生成。方法如下,
1 # Use below code to generate instance directly without via py interface 2 # ru_control = client.Dispatch("RuMaster.RuControl") 3 # ru_control = client.Dispatch("{75BF5D19-5AB0-4004-97EE-F039164681A3}")
此处若提示如下报错,则可能是硬件不存在导致的无法找到文件,从而无法生成实例,
1 # Note: Hardware is required to generate above instance, otherwise an error raised as below shows, 2 # pywintypes.com_error: (-2147024894, 'The system cannot find the file specified.', None, None)
最后,利用生成的实例即可以调用内部的函数了。
1 # Call inside function 2 ru_control.MasterReady()
2 使用comtypes
这里利用另外一个comtypes来实现对COM组件的调用。
2.1 环境搭建
利用pip安装所需要的comtypes包,
1 pip install comtypes
2.2 生成COM组件对象实例
利用comtypes包可以直接对COM组件进行对象创建,不通过中间层,类似于win32com的dispatch,使用方式如下,
from comtypes.client import CreateObject # ru_control = CreateObject("RuMaster.RuControl") ru_control = CreateObject("{75BF5D19-5AB0-4004-97EE-F039164681A3}") ru_control.MasterReady()
相关阅读
1. 动态链接库及辅助工具
参考链接