在 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 atexit
import ctypes
import ctypes.wintypes
import traceback
import uuid
HRESULT = ctypes.wintypes.DWORD
LCID = ctypes.wintypes.DWORD
DISPID = ctypes.wintypes.INT
SCODE = ctypes.wintypes.DWORD
VARTYPE = ctypes.c_ushort
S_OK = 0
def __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_low
self.Data2 = iid.time_mid
self.Data3 = iid.time_hi_version
data = iid.bytes
for 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.value
REFGUID = 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_"]