home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Shareware / Comunicatii / jyte / jyte.exe / universal.py < prev    next >
Text File  |  2004-01-26  |  8KB  |  191 lines

  1. # Code that packs and unpacks the Univgw structures.
  2.  
  3. # See if we have a special directory for the binaries (for developers)
  4. import types
  5. import pythoncom
  6. from win32com.client import gencache
  7.  
  8. com_error = pythoncom.com_error
  9. _univgw = pythoncom._univgw
  10.  
  11. def RegisterInterfaces(typelibGUID, lcid, major, minor, interface_names = None):
  12.     ret = [] # return a list of (dispid, funcname for our policy's benefit
  13.     # First see if we have makepy support.  If so, we can probably satisfy the request without loading the typelib.
  14.     try:
  15.         mod = gencache.GetModuleForTypelib(typelibGUID, lcid, major, minor)
  16.     except ImportError:
  17.         mod = None
  18.     if mod is None:
  19.         import win32com.client.build
  20.         # Load up the typelib and build (but don't cache) it now
  21.         tlb = pythoncom.LoadRegTypeLib(typelibGUID, major, minor, lcid)
  22.         typecomp_lib = tlb.GetTypeComp()
  23.         if interface_names is None:
  24.           interface_names = []
  25.           for i in range(tlb.GetTypeInfoCount()):
  26.             info = tlb.GetTypeInfo(i)
  27.             doc = tlb.GetDocumentation(i)
  28.             attr = info.GetTypeAttr()
  29.             if attr.typekind == pythoncom.TKIND_INTERFACE or \
  30.                (attr.typekind == pythoncom.TKIND_DISPATCH and attr.wTypeFlags & pythoncom.TYPEFLAG_FDUAL):
  31.                 interface_names.append(doc[0])
  32.         for name in interface_names:
  33.             type_info, type_comp = typecomp_lib.BindType(name, )
  34.             # If we got back a Dispatch interface, convert to the real interface.
  35.             attr = type_info.GetTypeAttr()
  36.             if attr.typekind == pythoncom.TKIND_DISPATCH:
  37.                 refhtype = type_info.GetRefTypeOfImplType(-1)
  38.                 type_info = type_info.GetRefTypeInfo(refhtype)
  39.                 attr = type_info.GetTypeAttr()
  40.             item = win32com.client.build.VTableItem(type_info, attr, type_info.GetDocumentation(-1))
  41.             _doCreateVTable(item.clsid, item.python_name, item.bIsDispatch, item.vtableFuncs)
  42.             for info in item.vtableFuncs:
  43.                 names, dispid, desc = info
  44.                 invkind = desc[4]
  45.                 ret.append((dispid, invkind, names[0]))
  46.     else:
  47.         # Cool - can used cached info.
  48.         if not interface_names:
  49.             interface_names = mod.VTablesToClassMap.values()
  50.         for name in interface_names:
  51.             try:
  52.                 iid = mod.NamesToIIDMap[name]
  53.             except KeyError:
  54.                 raise ValueError, "Interface '%s' does not exist in this cached typelib" % (name,)
  55. #            print "Processing interface", name
  56.             sub_mod = gencache.GetModuleForCLSID(iid)
  57.             is_dispatch = getattr(sub_mod, name + "_vtables_dispatch_", None)
  58.             method_defs = getattr(sub_mod, name + "_vtables_", None)
  59.             if is_dispatch is None or method_defs is None:
  60.                 raise ValueError, "Interface '%s' is IDispatch only" % (name,)
  61.  
  62.             # And create the univgw defn
  63.             _doCreateVTable(iid, name, is_dispatch, method_defs)
  64.             for info in method_defs:
  65.                 names, dispid, desc = info
  66.                 invkind = desc[4]
  67.                 ret.append((dispid, invkind, names[0]))
  68.     return ret
  69.  
  70. def _doCreateVTable(iid, interface_name, is_dispatch, method_defs):
  71.     defn = Definition(iid, is_dispatch, method_defs)
  72.     vtbl = _univgw.CreateVTable(defn, is_dispatch)
  73.     _univgw.RegisterVTable(vtbl, iid, interface_name)
  74.  
  75. def _CalcTypeSize(typeTuple):
  76.     t = typeTuple[0]
  77.     if t & (pythoncom.VT_BYREF | pythoncom.VT_ARRAY):
  78.         # Its a pointer.
  79.         cb = _univgw.SizeOfVT(pythoncom.VT_PTR)[1]
  80.     elif t == pythoncom.VT_RECORD:
  81.         # Just because a type library uses records doesn't mean the user
  82.         # is trying to.  We need to better place to warn about this, but it
  83.         # isn't here.
  84.         #try:
  85.         #    import warnings
  86.         #    warnings.warn("warning: records are known to not work for vtable interfaces")
  87.         #except ImportError:
  88.         #    print "warning: records are known to not work for vtable interfaces"
  89.         cb = _univgw.SizeOfVT(pythoncom.VT_PTR)[1]
  90.         #cb = typeInfo.GetTypeAttr().cbSizeInstance
  91.     else:
  92.         cb = _univgw.SizeOfVT(t)[1]
  93.     return cb
  94.  
  95. class Arg:
  96.     def __init__(self, arg_info, name = None):
  97.         self.name = name
  98.         self.vt, self.inOut, self.default, self.clsid = arg_info
  99.         self.size = _CalcTypeSize(arg_info)
  100.         # Offset from the beginning of the arguments of the stack.
  101.         self.offset = 0
  102.  
  103. class Method:
  104.     def __init__(self, method_info, isEventSink=0):
  105.         all_names, dispid, desc = method_info
  106.         name = all_names[0]
  107.         names = all_names[1:]
  108.         invkind = desc[4]
  109.         arg_defs = desc[2]
  110.         ret_def = desc[8]
  111.         
  112.         self.dispid = dispid
  113.         self.invkind = invkind
  114.         # We dont use this ATM.
  115. #        self.ret = Arg(ret_def)
  116.         if isEventSink and name[:2] != "On":
  117.             name = "On%s" % name
  118.         self.name = name
  119.         cbArgs = 0
  120.         self.args = []
  121.         for argDesc in arg_defs:
  122.             arg = Arg(argDesc)
  123.             arg.offset = cbArgs
  124.             cbArgs = cbArgs + arg.size
  125.             self.args.append(arg)
  126.         self.cbArgs = cbArgs
  127.         self._gw_in_args = self._GenerateInArgTuple()
  128.         self._gw_out_args = self._GenerateOutArgTuple()
  129.  
  130.     def _GenerateInArgTuple(self):
  131.         # Given a method, generate the in argument tuple
  132.         l = []
  133.         for arg in self.args:
  134.             if arg.inOut & pythoncom.PARAMFLAG_FIN or \
  135.                  arg.inOut == 0:
  136.                 l.append((arg.vt, arg.offset, arg.size))
  137.         return tuple(l)
  138.  
  139.     def _GenerateOutArgTuple(self):
  140.         # Given a method, generate the out argument tuple
  141.         l = []
  142.         for arg in self.args:
  143.             if arg.inOut & pythoncom.PARAMFLAG_FOUT or \
  144.                arg.inOut & pythoncom.PARAMFLAG_FRETVAL or \
  145.                arg.inOut == 0:
  146.                 l.append((arg.vt, arg.offset, arg.size, arg.clsid))
  147.         return tuple(l)
  148.  
  149. class Definition:
  150.     def __init__(self, iid, is_dispatch, method_defs):
  151.         self._iid = iid
  152.         self._methods = []
  153.         self._is_dispatch = is_dispatch
  154.         for info in method_defs:
  155.             entry = Method(info)
  156.             self._methods.append(entry)
  157.     def iid(self):
  158.         return self._iid
  159.     def vtbl_argsizes(self):
  160.         return map(lambda m: m.cbArgs, self._methods)
  161.     def dispatch(self, ob, index, argPtr,
  162.                  ReadFromInTuple=_univgw.ReadFromInTuple,
  163.                  WriteFromOutTuple=_univgw.WriteFromOutTuple):
  164.         "Dispatch a call to an interface method."
  165.         meth = self._methods[index]
  166.         # Infer S_OK if they don't return anything bizarre.
  167.         hr = 0 
  168.         args = ReadFromInTuple(meth._gw_in_args, argPtr)
  169.         # If ob is a dispatcher, ensure a policy
  170.         ob = getattr(ob, "policy", ob)
  171.         # Ensure the correct dispid is setup
  172.         ob._dispid_to_func_[meth.dispid] = meth.name
  173.         retVal = ob._InvokeEx_(meth.dispid, 0, meth.invkind, args, None, None)
  174.         # None is an allowed return value stating that
  175.         # the code doesn't want to touch any output arguments.
  176.         if type(retVal) == types.TupleType: # Like pythoncom, we special case a tuple.
  177.             # However, if they want to return a specific HRESULT,
  178.             # then they have to return all of the out arguments
  179.             # AND the HRESULT.
  180.             if len(retVal) == len(meth._gw_out_args) + 1:
  181.                 hr = retVal[0]
  182.                 retVal = retVal[1:]
  183.             else:
  184.                 raise TypeError, "Expected %s return values, got: %s" % (len(meth._gw_out_args) + 1, len(retVal))
  185.         else:
  186.             retVal = [retVal]
  187.             retVal.extend([None] * (len(meth._gw_out_args)-1))
  188.             retVal = tuple(retVal)
  189.         WriteFromOutTuple(retVal, meth._gw_out_args, argPtr)
  190.         return hr
  191.