home *** CD-ROM | disk | FTP | other *** search
/ PC World 2002 May / PCWorld_2002-05_cd.bin / Software / TemaCD / activepython / ActivePython-2.1.1.msi / Python21_win32com_universal.py < prev    next >
Encoding:
Python Source  |  2001-07-26  |  6.8 KB  |  165 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 pythoncom
  5. from pythoncom import com_error
  6. import types
  7. from pythoncom import _univgw
  8. from win32com.client import gencache
  9.  
  10. # Make it clear to the user they are playing with fire ATM ;-)
  11. msg = "win32com.universal is a very new module - it probably has bugs, and the interface may change in the future.  Use at your own risk!"
  12. try:
  13.     import warnings
  14.     warnings.warn(msg)
  15. except ImportError:
  16.     print msg
  17.  
  18.  
  19. def RegisterInterfaces(typelibGUID, lcid, major, minor, interface_names = None):
  20.     # First see if we have makepy support.  If so, we can probably satisfy the request without loading the typelib.
  21.     try:
  22.         mod = gencache.GetModuleForTypelib(typelibGUID, lcid, major, minor)
  23.     except ImportError:
  24.         mod = None
  25.     if mod is None:
  26.         import win32com.client.build
  27.         # Load up the typelib and build (but don't cache) it now
  28.         tlb = pythoncom.LoadRegTypeLib(typelibGUID, major, minor, lcid)
  29.         typecomp_lib = tlb.GetTypeComp()
  30.         for name in interface_names:
  31.             type_info, type_comp = typecomp_lib.BindType(name, )
  32.             # If we got back a Dispatch interface, convert to the real interface.
  33.             attr = type_info.GetTypeAttr()
  34.             if attr.typekind == pythoncom.TKIND_DISPATCH:
  35.                 refhtype = type_info.GetRefTypeOfImplType(-1)
  36.                 type_info = type_info.GetRefTypeInfo(refhtype)
  37.                 attr = type_info.GetTypeAttr()
  38.             item = win32com.client.build.VTableItem(type_info, attr, type_info.GetDocumentation(-1))
  39.             _doCreateVTable(item.clsid, item.python_name, item.bIsDispatch, item.vtableFuncs)
  40.     else:
  41.         # Cool - can used cached info.
  42.         if not interface_names:
  43.             interface_names = mod.VTablesNamesToCLSIDMap.keys()
  44.         for name in interface_names:
  45.             try:
  46.                 iid = mod.VTablesNamesToCLSIDMap[name]
  47.             except KeyError:
  48.                 raise ValueError, "Interface '%s' does not exist in this cached typelib" % (name,)
  49. #            print "Processing interface", name
  50.             sub_mod = gencache.GetModuleForCLSID(iid)
  51.             is_dispatch = getattr(sub_mod, name + "_vtables_dispatch_")
  52.             method_defs = getattr(sub_mod, name + "_vtables_")
  53.             # And create the univgw defn
  54.             _doCreateVTable(iid, name, is_dispatch, method_defs)
  55.  
  56. def _doCreateVTable(iid, interface_name, is_dispatch, method_defs):
  57.     defn = Definition(iid, is_dispatch, method_defs)
  58.     vtbl = _univgw.CreateVTable(defn, is_dispatch)
  59.     _univgw.RegisterVTable(vtbl, iid, interface_name)
  60.  
  61. def _CalcTypeSize(typeTuple):
  62.     t = typeTuple[0]
  63.     if t & pythoncom.VT_BYREF:
  64.         # Its a pointer.
  65.         cb = _univgw.SizeOfVT(pythoncom.VT_PTR)[1]
  66.     elif t == pythoncom.VT_RECORD:
  67.         try:
  68.             import warnings
  69.             warnings.warn("assuming records always pass pointers (they wont work for other reasons anyway!")
  70.         except ImportError:
  71.             print "warning: assuming records always pass pointers (they wont work for other reasons anyway!"
  72.         cb = _univgw.SizeOfVT(pythoncom.VT_PTR)[1]
  73.         #cb = typeInfo.GetTypeAttr().cbSizeInstance
  74.     else:
  75.         cb = _univgw.SizeOfVT(t)[1]
  76.     return cb
  77.  
  78. class Arg:
  79.     def __init__(self, arg_info, name = None):
  80.         self.vt, self.inOut, self.GUID = arg_info
  81.         self.size = _CalcTypeSize(arg_info)
  82.         # Offset from the beginning of the arguments of the stack.
  83.         self.offset = 0
  84.  
  85. class Method:
  86.     def __init__(self, method_info, isEventSink=0):
  87.         name, dispid, arg_defs, ret_def, names = method_info
  88.         self.dispid = dispid
  89.         # We dont use this ATM.
  90. #        self.ret = Arg(ret_def)
  91.         if isEventSink and name[:2] != "On":
  92.             name = "On%s" % name
  93.         self.name = name
  94.         cbArgs = 0
  95.         self.args = []
  96.         for argDesc in arg_defs:
  97.             arg = Arg(argDesc)
  98.             arg.offset = cbArgs
  99.             cbArgs = cbArgs + arg.size
  100.             self.args.append(arg)
  101.         self.cbArgs = cbArgs
  102.         self._gw_in_args = self._GenerateInArgTuple()
  103.         self._gw_out_args = self._GenerateOutArgTuple()
  104.  
  105.     def _GenerateInArgTuple(self):
  106.         # Given a method, generate the in argument tuple
  107.         l = []
  108.         for arg in self.args:
  109.             if arg.inOut & pythoncom.PARAMFLAG_FIN or \
  110.                  arg.inOut == 0:
  111.                 l.append((arg.vt, arg.offset, arg.size))
  112.         return tuple(l)
  113.  
  114.     def _GenerateOutArgTuple(self):
  115.         # Given a method, generate the out argument tuple
  116.         l = []
  117.         for arg in self.args:
  118.             if arg.inOut & pythoncom.PARAMFLAG_FOUT or \
  119.                arg.inOut & pythoncom.PARAMFLAG_FRETVAL or \
  120.                arg.inOut == 0:
  121.                 l.append((arg.vt, arg.offset, arg.size))
  122.         return tuple(l)
  123.  
  124. class Definition:
  125.     def __init__(self, iid, is_dispatch, method_defs):
  126.         self._iid = iid
  127.         self._methods = []
  128.         self._is_dispatch = is_dispatch
  129.         for info in method_defs:
  130.             entry = Method(info)
  131.             self._methods.append(entry)
  132.     def iid(self):
  133.         return self._iid
  134.     def vtbl_argsizes(self):
  135.         return map(lambda m: m.cbArgs, self._methods)
  136.     def dispatch(self, ob, index, argPtr,
  137.                  ReadFromInTuple=_univgw.ReadFromInTuple,
  138.                  WriteFromOutTuple=_univgw.WriteFromOutTuple):
  139.         "Dispatch a call to an interface method."
  140. #        import pywin.debugger;pywin.debugger.brk()
  141.         meth = self._methods[index]
  142.         # Infer S_OK if they don't return anything bizarre.
  143.         hr = 0 
  144.         args = ReadFromInTuple(meth._gw_in_args, argPtr)
  145.         # Ensure the correct dispid is setup
  146.         ob._dispid_to_func_[meth.dispid] = meth.name
  147.         retVal = ob._InvokeEx_(meth.dispid, 0, pythoncom.DISPATCH_METHOD, args, None, None)
  148.         # None is an allowed return value stating that
  149.         # the code doesn't want to touch any output arguments.
  150.         if type(retVal) == types.TupleType: # Like win32com, we special case a tuple.
  151.             # However, if they want to return a specific HRESULT,
  152.             # then they have to return all of the out arguments
  153.             # AND the HRESULT.
  154.             if len(retVal) == len(meth._gw_out_args) + 1:
  155.                 hr = retVal[0]
  156.                 retVal = retVal[1:]
  157.             else:
  158.                 raise TypeError, "Expected %s return values, got: %s" % (len(outTup), len(retVal))
  159.         else:
  160.             retVal = [retVal]
  161.             retVal.extend([None] * (len(meth._gw_out_args)-1))
  162.             retVal = tuple(retVal)
  163.         WriteFromOutTuple(retVal, meth._gw_out_args, argPtr)
  164.         return hr
  165.