Your changes look reasonable for the job they are designed to do, but doesn't provide a general solution I can try to adopt (which is fine!). Ultimately though, the question is "why does autocad's typelib not match its behaviour?". Can you find a reference to an autocad bug about this, or is it worth contacting their support with a request for assistance? It may turn out that both/either autocad or pywin32 are "correct", but incomplete in some subtle way - eg, if autocad could explain why it is *not* a bug in their typelib, it may help work out what bit of the puzzle is missing.
Another alternative would be for pywin32 to grow a way to easily indicate exact types to be passed in Variant calls. For example, your code could say something like: v = Variant(VT_DOUBLE, (1.0, 2.0, 3.0)) ms.AddPoint(v) This needn't be that hard. The "Variant" object could be a class defined in a .py file. The IDispatch::Invoke method would grow support for detecting this object and forming the correct Variant. The only query would be how InvokeTypes should handle such an object - ignoring the explicitly passed typeinfo seems wrong (but does seem practical!) I'd be happy to assist with this, but am unlikely to actually drive it until I personally need it. Sadly I don't think autocad will be used by me in the near future :) Mark > -----Original Message----- > From: [EMAIL PROTECTED] > [mailto:[EMAIL PROTECTED] Behalf Of Dan Glassman > Sent: Thursday, 26 January 2006 6:29 AM > To: python-win32@python.org > Subject: [python-win32] Autocad automation via COM: Passing coordinates > as arguments (suggested fix within) > > > > From: wccppp <[EMAIL PROTECTED]> > > Subject: [python-win32] question about COM again: variable type? > > > > [code] > > ms.AddPoint([0.0, 0.0, 0.0]) # this line gives the problem > > [/code] > > > > # Result is of type IAcadPoint > > def AddPoint(self, Point=defaultNamedNotOptArg): > > """Creates a Point object at a given location""" > > ret = self._oleobj_.InvokeTypes(1562, LCID, 1, (9, 0), ((12, > > 1),),Point) > > if ret is not None: > > ret = Dispatch(ret, 'AddPoint', > > '{35AF3AB5-755E-4AC9-8BAF-31B532870751}', UnicodeToString=0) > > return ret > > > Sorry for the long reply. > > The type library for AutoCad 2006 says that coordinates should be > passed as variants, so makepy's output is correct. But you can change > the makepy-generated file to process the argument as an array of doubles > instead of a variant and it will work. I'm not sure if that's because > the interface will also accept a 'raw' array, or if pythoncom is > magically wrapping the array in a variant. > > Taking from the AddPoint method of the IAcadModelSpace class that you've > included: > > [code] > ret = self._oleobj_.InvokeTypes(1562, LCID, 1, (9, 0), ((12, 1),),Point) > [/code] > > The (12, 1) part describes the Point argument as an (Variant, Input), > roughly. This should be changed to (8197, 1), which is (Array of > Doubles, Input): > > [code] > ret = self._oleobj_.InvokeTypes(1562, LCID, 1, (9, 0),((8197,1),),Point) > [/code] > > Unfortunately, this happens all over the place -- not just the AddPoint > method. It would be very tedious to go through makepy's output and > make the >1500 changes. (12, 1) cannot be changed globally in there. It > also happens for more than just coordinate arguments; the Select methods > of SelectionSet objects have filters which are also arrays wrapped in a > variant. I haven't run across any others; the code below fixes > everything I've found. > > My solution was to change build.py (does some of makepy's work; located > in %pythoninstalldir%\lib\site-packages\win32com\client\) to apply this > Variant -> Array change for me when processing the type library. The > line numbers I reference are from pywin32 2.07; I tried to include > enough context to find the right parts of build.py in case yours is > different. > > My understanding of COM is not good, and these changes to build.py don't > seem suitably robust. It does a small check to see if it's processing > an Autocad library, but I suggest restoring build.py to its original > state after processing your Autocad type libraries. You'll lose these > fixes for dynamic dispatch in that case. > > I would be grateful if somebody could point out any red flags or suggest > a better approach. > > Near the top of build.py (~line 52): > > [code] > NoTranslateMap = {} > for v in NoTranslateTypes: > NoTranslateMap[v] = None > > #My addition starts here > AutocadTranslateMap = { > ('alignpoint','anglevertex','arccenter','arcpoint','axisdir', > 'axispoint','basepoint','boundry','center','centerpoint', > 'chordpoint','controlpoint','controlpoints','coordinates', > 'definitionpoint','dimlinelocation','direction', > 'directionvector','endpoint','endtangent','extline1point', > 'extline1startpoint','extline2endpoint','extline2point', > 'extline2startpoint','farchordpoint','firstendpoint','fitpoint', > 'fitpoints','frompoint','insertionpoint','inspoint','jogpoint', > 'knots','knotvalues','leader1point','leader2point', > 'leaderendpoint','limits','lowerleft','lowleft','majoraxis', > 'normal','origin','overridecenter','overridecenterpos', > 'plotorigin','point','point1','point2','point3','point4', > 'pointsarray','pointslist','pointsmatrix','porigin', > 'secondendpoint','secondpoint','snapbasepoint','startpoint', > 'starttangent','target','targetpoint','textalignmentpoint', > 'textpoint','textpos','textposition','topoint', > 'transformationmatrix','upperright','vertex','vertexlist', > 'vertices','verticeslist','weights','wpt','wpt1','wpt2', > 'xaxispoint','xline1point','xline2point','xvector', > 'yaxispoint','yvector'): 8197, > ('filtertype',): 8193, > ('filterdata',): 8204 > } > #My addition ends here > > class MapEntry: > "Simple holder for named attibutes - items in a map." > def __init__(self, desc_or_id, names=None, doc=None, > resultCLSID=pythoncom.IID_NULL, resultDoc = None, hidden=0): > [/code] > > Then, in the _AddFunc_ method of class DispatchItem (~line 175): > > Note that the code below has been stripped of its indentation to > hopefully make it more readable in email. Indentation within the posted > code is correct, but the entire code block needs to be indented to match > its context in build.py. > > [code] > fdesc.rettype = typerepr, flag, defval, resultCLSID > # Translate any Alias or Enums in argument list. > argList = [] > > #Changes begin here; > #for argDesc in fdesc.args: > for index, argDesc in enumerate(fdesc.args): > typerepr, flag, defval = argDesc > > #Catch only if reasonably sure this is Autocad > if self.python_name[:5] == 'IAcad': > #Catch (VT_VARIANT, FIN) and (VT_VARIANT, FIN|FOPT) > #Outputs seem to translate into tuples just fine already > if typerepr == 12 and (flag == 1 or flag == 17): > if len(fdesc.args) == len(names): #???Properties??? > replace = [key for key in AutocadTranslateMap.keys() \ > if names[index].lower() in key] > if replace: > typerepr = AutocadTranslateMap[replace[0]] > else: #names[0] is method name; names[1:] is arg names > replace = [key for key in AutocadTranslateMap.keys() \ > if names[index+1].lower() in key] > if replace: > typerepr = AutocadTranslateMap[replace[0]] > #Changes end here; > > arg_type, arg_clsid, arg_doc = _ResolveType(typerepr, typeinfo) > > argDesc = arg_type, flag, defval, arg_clsid > # sys.stderr.write("%s\n" % (argDesc[0],)) > argList.append(argDesc) > fdesc.args = tuple(argList) > [/code] > _______________________________________________ > Python-win32 mailing list > Python-win32@python.org > http://mail.python.org/mailman/listinfo/python-win32 > _______________________________________________ Python-win32 mailing list Python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32