PyXR

c:\python24\lib\site-packages\win32 \ com \ universal.py



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
SourceForge.net Logo