Python 3 中调用 COM 的库文件

来源:互联网 发布:手机播放器软件 编辑:程序博客网 时间:2024/06/05 08:27

在 Python 2.x 时代貌似有支持 COM的。 http://svn.python.org/projects/ctypes/tags/release_0_6_2/ctypes/win32/com/__init__.py 这个 win32 的 COM 包到了 3.x 时代就不见了。从那里参考和借鉴了很多,也被误导了很多,因为从 2.x 到 3.x 变化很大,而且那个包里面也有很多地方写得不够好。

闲话少说,直接贴代码。没加注释,也省略一些复杂 Interface 的定义。

import atexitimport ctypesimport ctypes.wintypesimport tracebackimport uuidHRESULT= ctypes.wintypes.DWORDLCID= ctypes.wintypes.DWORDDISPID= ctypes.wintypes.INTSCODE= ctypes.wintypes.DWORDVARTYPE= ctypes.c_ushortS_OK= 0def __init__():ctypes.oledll.ole32.CoInitialize(None)atexit.register(ctypes.oledll.ole32.CoUninitialize)__init__()class GUID(ctypes.Structure):_fields_ = [("Data1", ctypes.wintypes.DWORD),("Data2", ctypes.wintypes.WORD),("Data3", ctypes.wintypes.WORD),("Data4", ctypes.wintypes.BYTE*8)]def __init__(self, name=None):iid = uuid.UUID(name)self.Data1 = iid.time_lowself.Data2 = iid.time_midself.Data3 = iid.time_hi_versiondata = iid.bytesfor i in range(8):self.Data4[i] = ctypes.wintypes.BYTE(data[8+i])def __str__(self):s = (ctypes.c_wchar*39)()ctypes.oledll.ole32.StringFromGUID2(ctypes.byref(self), s, 39)return s.valueREFGUID = REFIID = RIID = ctypes.POINTER(GUID)class _InterfaceMetaclass(type(ctypes.Structure)):def __new__(cls, name, bases, kwds):if "_methods_" in kwds and "_methods_" in bases[0].__dict__:kwds["_methods_"] = bases[0]._methods_+kwds["_methods_"]lpVTable = ctypes.POINTER(name+"_VTable")kwds["_fields_"] = [("lpVtbl", lpVTable)]newcls = super().__new__(cls, name, bases, kwds)newcls.lpVTable = lpVTableif "_methods_" in kwds:"""make methods"""newcls._com_methods_ = {}i = 0for func, proto in kwds["_methods_"]:newcls._com_methods_[func] = proto(i, func)setattr(newcls, func, newcls._InvokeComMethod)i += 1return newclsclass IUnknown(ctypes.Structure, metaclass = _InterfaceMetaclass):def _InvokeComMethod(self, *args):func = traceback.extract_stack()[-2][-1].split('.')[1].split('(')[0]return self._com_methods_[func](ctypes.c_void_p(ctypes.addressof(self)), *args)_iid_ = GUID("{618736E0-3C3D-11CF-810C-00AA00389B71}")PIUnknown = ctypes.POINTER(IUnknown)def from_param(self, obj):if (type(obj) == type(ctypes.byref(ctypes.c_int())) and issubclass(obj._obj._type_, IUnknown)) \   or (isinstance(obj, ctypes._Pointer) and issubclass(obj._type_._type, IUnknown)):return objraise TypeError("expected a reference to IUnknown instead of "+str(type(obj)))ctypes.POINTER(PIUnknown).from_param = classmethod(from_param)def STDMETHOD(restype, name, *argtypes, **kw):return name, ctypes.WINFUNCTYPE(restype, *argtypes)IUnknown._methods_ = [STDMETHOD(HRESULT, "QueryInterface", REFIID, ctypes.POINTER(PIUnknown)),                      STDMETHOD(ctypes.wintypes.ULONG, "AddRef"),                      STDMETHOD(ctypes.wintypes.ULONG, "Release")]IUnknown = _InterfaceMetaclass("IUnknown", (ctypes.Structure,), {"_methods_": IUnknown._methods_, "_iid_": IUnknown._iid_, "_InvokeComMethod": IUnknown._InvokeComMethod})PIUnknown = ctypes.POINTER(IUnknown)class ITypeInfo(IUnknown, metaclass = _InterfaceMetaclass):_iid_ = GUID("{00020401-0000-0000-C000-000000000046}")class IDispatch(IUnknown, metaclass = _InterfaceMetaclass):_iid_ = GUID("{00020400-0000-0000-C000-000000000046}")class BSTR(ctypes.c_wchar_p):def __del__(self):ctypes.oledll.oleaut32.SysFreeString(self)def __repr__(self):return self.value"""http://msdn.microsoft.com/en-us/library/windows/desktop/dd373687(v=vs.85).aspx"""class VARIANT(ctypes.Structure):class _U(ctypes.Union):_fields_ = [("lVal", ctypes.wintypes.LONG),# VT_I4            ("pdispVal", ctypes.POINTER(IDispatch)),# VT_IDISPATCH            ("bstrVal", BSTR)]# VT_BSTR_anonymous_ = ("_u",)_fields_ = [("vt", VARTYPE),            ("wReserved1", ctypes.wintypes.WORD),            ("wReserved2", ctypes.wintypes.WORD),            ("wReserved3", ctypes.wintypes.WORD),            ("_u", _U)]class DISPPARAMS(ctypes.Structure):_fields_ = [("rgvarg", ctypes.POINTER(VARIANT)),            ("rgdispidNamedArgs", ctypes.POINTER(DISPID)),            ("cArgs", ctypes.wintypes.UINT),            ("cNamedArgs", ctypes.wintypes.UINT)]class EXCEPINFO(ctypes.Structure):_fields_ = [("wCode", ctypes.wintypes.WORD),            ("wReserved", ctypes.wintypes.WORD),                ("bstrSource", BSTR),                ("bstrDescription", BSTR),                ("bstrHelpFile", BSTR),                ("dwHelpContext", ctypes.wintypes.DWORD),                ("pvReserved", ctypes.c_void_p),                ("pfnDeferredFillIn", ctypes.c_void_p), # XXX                ("scode", SCODE)]IDispatch._methods_ = [STDMETHOD(HRESULT, "GetTypeInfoCount", ctypes.wintypes.UINT),                       STDMETHOD(HRESULT, "GetTypeInfo", ctypes.wintypes.UINT, LCID, ctypes.POINTER(ctypes.POINTER(ITypeInfo))),                       STDMETHOD(HRESULT, "GetIDsOfNames", REFIID, ctypes.wintypes.LPOLESTR, ctypes.wintypes.ULONG, LCID, ctypes.POINTER(DISPID)),                       STDMETHOD(HRESULT, "Invoke", DISPID, REFIID, LCID, ctypes.wintypes.WORD, ctypes.POINTER(DISPPARAMS), ctypes.POINTER(VARIANT), ctypes.POINTER(EXCEPINFO), ctypes.wintypes.UINT)]IDispatch = _InterfaceMetaclass("IDispatch", (IUnknown,), {"_methods_": IDispatch._methods_})PIDispatch = ctypes.POINTER(IDispatch)class IAccessible(IDispatch, metaclass = _InterfaceMetaclass):_iid_ = GUID("{618736E0-3C3D-11CF-810C-00AA00389B71}")_methods_ = [STDMETHOD(HRESULT, "get_accParent", ctypes.POINTER(PIDispatch)),             STDMETHOD(HRESULT, "get_accChildCount", ctypes.POINTER(ctypes.c_long)),             STDMETHOD(HRESULT, "get_accChild", VARIANT, ctypes.POINTER(PIDispatch)),             STDMETHOD(HRESULT, "get_accName", VARIANT, ctypes.POINTER(BSTR)),             STDMETHOD(HRESULT, "get_accValue", VARIANT, ctypes.POINTER(BSTR)),             STDMETHOD(HRESULT, "get_accDescription", VARIANT, ctypes.POINTER(BSTR)),             STDMETHOD(HRESULT, "get_accRole", VARIANT, ctypes.POINTER(VARIANT)),             STDMETHOD(HRESULT, "get_accState", VARIANT, ctypes.POINTER(VARIANT)),             STDMETHOD(HRESULT, "get_accHelp", VARIANT, ctypes.POINTER(BSTR)),             STDMETHOD(HRESULT, "get_accHelpTopic", ctypes.POINTER(BSTR), VARIANT, ctypes.POINTER(ctypes.c_long)),             STDMETHOD(HRESULT, "get_accKeyboardShortcut", VARIANT, ctypes.POINTER(BSTR)),             STDMETHOD(HRESULT, "get_accFocus", ctypes.POINTER(VARIANT)),             STDMETHOD(HRESULT, "get_accSelection", ctypes.POINTER(VARIANT)),             STDMETHOD(HRESULT, "get_accDefaultAction", VARIANT, ctypes.POINTER(BSTR)),             STDMETHOD(HRESULT, "accSelect", ctypes.c_long, VARIANT),             STDMETHOD(HRESULT, "accLocation", ctypes.POINTER(ctypes.c_long), ctypes.POINTER(ctypes.c_long), ctypes.POINTER(ctypes.c_long), ctypes.POINTER(ctypes.c_long), VARIANT),             STDMETHOD(HRESULT, "accNavigate", ctypes.c_long, VARIANT, ctypes.POINTER(VARIANT)),             STDMETHOD(HRESULT, "accHitTest", ctypes.c_long, ctypes.c_long, ctypes.POINTER(VARIANT)),             STDMETHOD(HRESULT, "accDoDefaultAction", VARIANT),             STDMETHOD(HRESULT, "put_accName", VARIANT, BSTR),# not supported             STDMETHOD(HRESULT, "put_accValue", VARIANT, BSTR)]PIAccessible = ctypes.POINTER(IAccessible)class IServiceProvider(IUnknown, metaclass = _InterfaceMetaclass):_iid_ = GUID("{6D5140C1-7436-11CE-8034-00AA006009FA}")_methods_ = [STDMETHOD(HRESULT, "QueryService", REFGUID, REFIID, ctypes.POINTER(PIUnknown))]PIServiceProvider = ctypes.POINTER(IServiceProvider)