A brief history of the Python multi-dispatch issue


For the most part, this is no longer a problem, although there may be a few cases where you have to use win32com.client.dynamic.Dispatch. A huge effort was put in to XSI 6.0 to get rid of this “dispatch” issue.

The main problem was that XSI used a technique called “Multi-Dispatch” rather than normal inheritance to organize the interfaces supported by each object in the Scripting Object Model. In the original SDK, this was designed to maintain binary ompatibility for the now-obsolete COM C++ API.

The problem was that because Python used optimizations to read and compile the contents of typelibs rather than communicating with XSI directly via IDispatch, objects did not always appear to have all the methods and properties that they are supposed to.

For XSI 6.0, the OM hierarchy was overhauled to use derivation and inheritance instead of the multi-dispatch mechanism.

Prior to XSI 6.0, the workaround was the __init__.py file hack, as described in this 2005 post to the XSI Mailing List by Jerry Gamache:

—–Original Message—–
From: owner-xsi@Softimage.COM [mailto:owner-xsi@Softimage.COM] On Behalf Of Jerry Gamache
Sent: March-17-05 2:23 PM
To: XSI@Softimage.COM
Subject: RE: avoiding using get value with python

XSI sometimes return objects with an incorrectly set (as per PythonWin standards) multi-dispatch interface.

The way to work around that is to re-wrap the object in a dynamic dispatch. This allows you to skip the Application.GetValue:

def dispFix( badDispatch ):
	import win32com.client.dynamic
	# Re-Wraps a bad dispatch into a working one:
	return win32com.client.dynamic.Dispatch(badDispatch)

# Let's see if this works:
Application.CreatePrim("Sphere", "MeshSurface", "", "")
Application.ApplyHairOp("sphere", "")
oHair = Application.GetValue("hair").ActivePrimitive.ConstructionHistory.Find("HairGenOp")
try:
	Application.LogMessage(oHair.Parameters['EmitterMeshSubdlevel'].Value)
except:
	Application.LogMessage("Incorrect dispatch pointer")
oHair = dispFix(oHair)
Application.LogMessage(oHair.Parameters['EmitterMeshSubdlevel'].Value)

# or, as a single long line:

dispFix(Application.GetValue("hair")  
	   .ActivePrimitive.ConstructionHistory 
	   .Find("HairGenOp")
	 ).Parameters['EmitterMeshSubdlevel'].Value = 1

If that really really annoys you and you don’t want to dispFix at all, there is a way to make sure everything works, but you need to modify a Python file to always return dynamic dispatches:

Change %PYTHONPATH%\Lib\site-packages\win32com\client\__init__.py

Look for the function called __WrapDispatch

And comment all lines except the last one that begins with “return dynamic.Dispatch( … ”

Of course it is always a good idea to backup files you are about to modify.

3 thoughts on “A brief history of the Python multi-dispatch issue

  1. As of Softimage 2010 I was still encountering multi dispatch issues especially when working with PPGs in self-installable plugins. I never really enjoyed patching on an as you go basis so I strongly suggest using the __init__.py fix.

    I’ve done so systematically for years and have never encountered issues inside or outside Softimage.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s