[python-win32] win32com gencache InvokeTypes and OUT/ByRef parameters

Hibiki Kanzaki hibikikanzaki at gmail.com
Thu Jun 11 22:58:11 CEST 2009


I am using a COM library from Python.  The methods
have OUT parameters, so I am using the gencache/makepy
facility of win32com.  When it generates the wrapper
files, there are function definitions like this one
(this is for accessing Visual SourceSafe COM Automation)

	# Result is of type IVSSItem
	# The method VSSItem is actually a property, but must be used as a
method to correctly pass the arguments
	def VSSItem(self, Spec=defaultNamedNotOptArg, Deleted=False):
		ret = self._oleobj_.InvokeTypes(6, LCID, 2, (9, 0), ((8, 1), (11, 49)),Spec
			, Deleted, ppIVSSItem)
		if ret is not None:
			ret = Dispatch(ret, u'VSSItem', '{2A0DE0E7-2E9F-11D0-9236-00AA00A1EB95}')
		return ret

When VSSItem() is called, it gets an error that ppVSSItem
is not defined... and as far as I can tell that is correct,
I do not see anything anywhere in the wrapper files where
it appears to define any "ppIVSSItem".  In this particular
case, I can manually edit that file and simply remove that
last argument, and then it works fine.  That code is in a
wrapper for VSSDatabase (IVSSDatabase).  When the VSSItem
object is created, a new file IVSSItem.py is created which
has the same problem-- InvokeTypes is passed arguments
which are names of variables which do not seem to exist.

I am not sure if I can get away with editing files
this way... especially in cases where the method does
not simply have one trailing OUT parameter. it would
be nice if I did not, especially since I do not get
all the wrappers at once-- they are generated only
when I try to instantiate another type of COM object
(indirectly, by calling methods of the other objects).

I am curious what is going on here... it looks like maybe
the wrapper is generated by MakeDispatchFuncMethod in
win32com/client/build.py, by code which looks like this:

		retDesc = fdesc[8][:2]
		argsDesc = tuple([what[:2] for what in fdesc[2]])
		# The runtime translation of the return types is expensive, so when
we know the
		# return type of the function, there is no need to check the type at runtime.
		# To qualify, this function must return a "simple" type, and have no
byref args.
		# Check if we have byrefs or anything in the args which mean we
still need a translate.
		param_flags = [what[1] for what in fdesc[2]]
		bad_params = [flag for flag in param_flags if flag &
(pythoncom.PARAMFLAG_FOUT | pythoncom.PARAMFLAG_FRETVAL)!=0]
		s = None
		if len(bad_params)==0 and len(retDesc)==2 and retDesc[1]==0:
			rd = retDesc[0]
			if rd in NoTranslateMap:
				s = '%s\treturn self._oleobj_.InvokeTypes(%d, LCID, %s, %s, %s%s)'
% (linePrefix, id, fdesc[4], retDesc, argsDesc, _BuildArgList(fdesc,
names))
			elif rd in [pythoncom.VT_DISPATCH, pythoncom.VT_UNKNOWN]:
				s = '%s\tret = self._oleobj_.InvokeTypes(%d, LCID, %s, %s,
%s%s)\n' % (linePrefix, id, fdesc[4], retDesc, repr(argsDesc),
_BuildArgList(fdesc, names))
				s = s + '%s\tif ret is not None:\n' % (linePrefix,)
				if rd == pythoncom.VT_UNKNOWN:
					s = s + "%s\t\t# See if this IUnknown is really an IDispatch\n" %
(linePrefix,)
					s = s + "%s\t\ttry:\n" % (linePrefix,)
					s = s + "%s\t\t\tret =
ret.QueryInterface(pythoncom.IID_IDispatch)\n" % (linePrefix,)
					s = s + "%s\t\texcept pythoncom.error:\n" % (linePrefix,)
					s = s + "%s\t\t\treturn ret\n" % (linePrefix,)
				s = s + '%s\t\tret = Dispatch(ret, %s, %s)\n' %
(linePrefix,repr(name), resclsid)
				s = s + '%s\treturn ret' % (linePrefix)
			elif rd == pythoncom.VT_BSTR:
				s = "%s\t# Result is a Unicode object\n" % (linePrefix,)
				s = s + '%s\treturn self._oleobj_.InvokeTypes(%d, LCID, %s, %s,
%s%s)' % (linePrefix, id, fdesc[4], retDesc, repr(argsDesc),
_BuildArgList(fdesc, names))
			# else s remains None

This code is opaque for me since I have no familiarity
with the code, or what is the correct behavior...

By the way this is build213 running with Python 2.6.
I have the same problem with build212.


More information about the python-win32 mailing list