This is not actually a script, but a solution I’ve found to a huge roadblock I encountered while trying to use Python to automate CATIA V5 using win32com AND use all funcionalities exposed to automation.
We all know it’s very easy to get started by just using late-binding (dynamic dispatch) and the more advanced users will already know that it will be not possible to use Subs that need Byref arrays. Developers of win32com related stuff are aware of the problem but not to the fact that in some applications these kind of Sub are very intensively used i.e. all subs to get triplets such as GetCoordinates of any class derived from the Point class, or GetFirstAxis of any class derived from the Plane class.
Developers state that it’s sufficient to switch to early bindig using makepy to solve the problem but in my case for CATIA V5 R19 it didn’t solve the problem at all, it even added more problems.
Type libraries/COM implementation of CATIA appear to be poorly specified in many cases. When looking at the variant type required by GetCoordinates (and all similar byref functions) described in the py generated from makepy, it specified 8204 that corresponds to pythoncom.VT_ARRAY | pythoncom.VT_VARIANT
It actually missed the VT_BYREF value.
I added it to the bit or operation getting 24588 for pythoncom.VT_ARRAY | pythoncom.VT_VARIANT | pythoncom.VT_BYREF.
After just saving the module, my script instatly worked by just passing and assigning to a tuple:
ptcoord = *3 ptcoord = point.GetCoordinates(ptcoord)
Another big, annoying roadblock that prevented me to even try to solve this issue, and this is still related to the poor TLB specification or COM implementation of CATIA V5. When switching to early-binding (forced by the need to use byref subs), specific classes are assigned to returned objects. But CATIA has some kind of “polymorphic” behaviour in some case. For instance, the type returned by CATIA.ActiveDocument is stated to be Document. But in reality, it will be a specific child of the Document class, i.e. PartDocument or ProductDocument. Early-binding will force the result to be Document because so is specified in the TLB. But the Document class has no property called Part, so there’s no way to get past this point because one can not get to the the Part object. Solution was to acquire the object using “temporary” dynamic dispatch, then use Dispatch() function on it to get the right specific type assigned.
This solved finally the last roadblock:
from win32com.client import Dispatch from win32com.client.dynamic import DumbDispatch CATIA = Dispatch('CATIA.Application') oDoc = Dispatch(DumbDispatch(CATIA.ActiveDocument)) oPart = oDoc.Part
To slightly improve the readability, I created a simple dedicated funcion:
from win32com.client import Dispatch from win32com.client.dynamic import DumbDispatch def GetRightDispatch(o): return Dispatch(DumbDispatch(o)) CATIA = Dispatch('CATIA.Application') oDoc = getRightDispatch(CATIA.ActiveDocument) oPart = oDoc.Part
So i use getRightDispatch() instead of direct assignment each time an COM object property is likely to return a type that is not the right type specified in a tlb, but a child of it. For instance:
Part.HybridShapeFactory (used to return Factory instead of HybridShapeFactory)
HybridShapes.Item(I) (used to return HybridShape instead of the specific HybridShape type)
Now the roads are open. Cheers