0001 # Code that packs and unpacks the Univgw structures. 0002 0003 # See if we have a special directory for the binaries (for developers) 0004 import types 0005 import pythoncom 0006 from win32com.client import gencache 0007 0008 com_error = pythoncom.com_error 0009 _univgw = pythoncom._univgw 0010 0011 def RegisterInterfaces(typelibGUID, lcid, major, minor, interface_names = None): 0012 ret = [] # return a list of (dispid, funcname for our policy's benefit 0013 # First see if we have makepy support. If so, we can probably satisfy the request without loading the typelib. 0014 try: 0015 mod = gencache.GetModuleForTypelib(typelibGUID, lcid, major, minor) 0016 except ImportError: 0017 mod = None 0018 if mod is None: 0019 import win32com.client.build 0020 # Load up the typelib and build (but don't cache) it now 0021 tlb = pythoncom.LoadRegTypeLib(typelibGUID, major, minor, lcid) 0022 typecomp_lib = tlb.GetTypeComp() 0023 if interface_names is None: 0024 interface_names = [] 0025 for i in range(tlb.GetTypeInfoCount()): 0026 info = tlb.GetTypeInfo(i) 0027 doc = tlb.GetDocumentation(i) 0028 attr = info.GetTypeAttr() 0029 if attr.typekind == pythoncom.TKIND_INTERFACE or \ 0030 (attr.typekind == pythoncom.TKIND_DISPATCH and attr.wTypeFlags & pythoncom.TYPEFLAG_FDUAL): 0031 interface_names.append(doc[0]) 0032 for name in interface_names: 0033 type_info, type_comp = typecomp_lib.BindType(name, ) 0034 # If we got back a Dispatch interface, convert to the real interface. 0035 attr = type_info.GetTypeAttr() 0036 if attr.typekind == pythoncom.TKIND_DISPATCH: 0037 refhtype = type_info.GetRefTypeOfImplType(-1) 0038 type_info = type_info.GetRefTypeInfo(refhtype) 0039 attr = type_info.GetTypeAttr() 0040 item = win32com.client.build.VTableItem(type_info, attr, type_info.GetDocumentation(-1)) 0041 _doCreateVTable(item.clsid, item.python_name, item.bIsDispatch, item.vtableFuncs) 0042 for info in item.vtableFuncs: 0043 names, dispid, desc = info 0044 invkind = desc[4] 0045 ret.append((dispid, invkind, names[0])) 0046 else: 0047 # Cool - can used cached info. 0048 if not interface_names: 0049 interface_names = mod.VTablesToClassMap.values() 0050 for name in interface_names: 0051 try: 0052 iid = mod.NamesToIIDMap[name] 0053 except KeyError: 0054 raise ValueError, "Interface '%s' does not exist in this cached typelib" % (name,) 0055 # print "Processing interface", name 0056 sub_mod = gencache.GetModuleForCLSID(iid) 0057 is_dispatch = getattr(sub_mod, name + "_vtables_dispatch_", None) 0058 method_defs = getattr(sub_mod, name + "_vtables_", None) 0059 if is_dispatch is None or method_defs is None: 0060 raise ValueError, "Interface '%s' is IDispatch only" % (name,) 0061 0062 # And create the univgw defn 0063 _doCreateVTable(iid, name, is_dispatch, method_defs) 0064 for info in method_defs: 0065 names, dispid, desc = info 0066 invkind = desc[4] 0067 ret.append((dispid, invkind, names[0])) 0068 return ret 0069 0070 def _doCreateVTable(iid, interface_name, is_dispatch, method_defs): 0071 defn = Definition(iid, is_dispatch, method_defs) 0072 vtbl = _univgw.CreateVTable(defn, is_dispatch) 0073 _univgw.RegisterVTable(vtbl, iid, interface_name) 0074 0075 def _CalcTypeSize(typeTuple): 0076 t = typeTuple[0] 0077 if t & (pythoncom.VT_BYREF | pythoncom.VT_ARRAY): 0078 # Its a pointer. 0079 cb = _univgw.SizeOfVT(pythoncom.VT_PTR)[1] 0080 elif t == pythoncom.VT_RECORD: 0081 # Just because a type library uses records doesn't mean the user 0082 # is trying to. We need to better place to warn about this, but it 0083 # isn't here. 0084 #try: 0085 # import warnings 0086 # warnings.warn("warning: records are known to not work for vtable interfaces") 0087 #except ImportError: 0088 # print "warning: records are known to not work for vtable interfaces" 0089 cb = _univgw.SizeOfVT(pythoncom.VT_PTR)[1] 0090 #cb = typeInfo.GetTypeAttr().cbSizeInstance 0091 else: 0092 cb = _univgw.SizeOfVT(t)[1] 0093 return cb 0094 0095 class Arg: 0096 def __init__(self, arg_info, name = None): 0097 self.name = name 0098 self.vt, self.inOut, self.default, self.clsid = arg_info 0099 self.size = _CalcTypeSize(arg_info) 0100 # Offset from the beginning of the arguments of the stack. 0101 self.offset = 0 0102 0103 class Method: 0104 def __init__(self, method_info, isEventSink=0): 0105 all_names, dispid, desc = method_info 0106 name = all_names[0] 0107 names = all_names[1:] 0108 invkind = desc[4] 0109 arg_defs = desc[2] 0110 ret_def = desc[8] 0111 0112 self.dispid = dispid 0113 self.invkind = invkind 0114 # We dont use this ATM. 0115 # self.ret = Arg(ret_def) 0116 if isEventSink and name[:2] != "On": 0117 name = "On%s" % name 0118 self.name = name 0119 cbArgs = 0 0120 self.args = [] 0121 for argDesc in arg_defs: 0122 arg = Arg(argDesc) 0123 arg.offset = cbArgs 0124 cbArgs = cbArgs + arg.size 0125 self.args.append(arg) 0126 self.cbArgs = cbArgs 0127 self._gw_in_args = self._GenerateInArgTuple() 0128 self._gw_out_args = self._GenerateOutArgTuple() 0129 0130 def _GenerateInArgTuple(self): 0131 # Given a method, generate the in argument tuple 0132 l = [] 0133 for arg in self.args: 0134 if arg.inOut & pythoncom.PARAMFLAG_FIN or \ 0135 arg.inOut == 0: 0136 l.append((arg.vt, arg.offset, arg.size)) 0137 return tuple(l) 0138 0139 def _GenerateOutArgTuple(self): 0140 # Given a method, generate the out argument tuple 0141 l = [] 0142 for arg in self.args: 0143 if arg.inOut & pythoncom.PARAMFLAG_FOUT or \ 0144 arg.inOut & pythoncom.PARAMFLAG_FRETVAL or \ 0145 arg.inOut == 0: 0146 l.append((arg.vt, arg.offset, arg.size, arg.clsid)) 0147 return tuple(l) 0148 0149 class Definition: 0150 def __init__(self, iid, is_dispatch, method_defs): 0151 self._iid = iid 0152 self._methods = [] 0153 self._is_dispatch = is_dispatch 0154 for info in method_defs: 0155 entry = Method(info) 0156 self._methods.append(entry) 0157 def iid(self): 0158 return self._iid 0159 def vtbl_argsizes(self): 0160 return map(lambda m: m.cbArgs, self._methods) 0161 def dispatch(self, ob, index, argPtr, 0162 ReadFromInTuple=_univgw.ReadFromInTuple, 0163 WriteFromOutTuple=_univgw.WriteFromOutTuple): 0164 "Dispatch a call to an interface method." 0165 meth = self._methods[index] 0166 # Infer S_OK if they don't return anything bizarre. 0167 hr = 0 0168 args = ReadFromInTuple(meth._gw_in_args, argPtr) 0169 # If ob is a dispatcher, ensure a policy 0170 ob = getattr(ob, "policy", ob) 0171 # Ensure the correct dispid is setup 0172 ob._dispid_to_func_[meth.dispid] = meth.name 0173 retVal = ob._InvokeEx_(meth.dispid, 0, meth.invkind, args, None, None) 0174 # None is an allowed return value stating that 0175 # the code doesn't want to touch any output arguments. 0176 if type(retVal) == types.TupleType: # Like pythoncom, we special case a tuple. 0177 # However, if they want to return a specific HRESULT, 0178 # then they have to return all of the out arguments 0179 # AND the HRESULT. 0180 if len(retVal) == len(meth._gw_out_args) + 1: 0181 hr = retVal[0] 0182 retVal = retVal[1:] 0183 else: 0184 raise TypeError, "Expected %s return values, got: %s" % (len(meth._gw_out_args) + 1, len(retVal)) 0185 else: 0186 retVal = [retVal] 0187 retVal.extend([None] * (len(meth._gw_out_args)-1)) 0188 retVal = tuple(retVal) 0189 WriteFromOutTuple(retVal, meth._gw_out_args, argPtr) 0190 return hr 0191
Generated by PyXR 0.9.4