[python-win32] Autocad automation via COM: Passing coordinates as arguments (suggested fix within)

Mark Hammond mhammond at skippinet.com.au
Fri Jan 27 01:53:32 CET 2006


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: python-win32-bounces at python.org
> [mailto:python-win32-bounces at python.org]On Behalf Of Dan Glassman
> Sent: Thursday, 26 January 2006 6:29 AM
> To: python-win32 at python.org
> Subject: [python-win32] Autocad automation via COM: Passing coordinates
> as arguments (suggested fix within)
>
>
> >  From: wccppp <wccppp@[...].com>
> >  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 at python.org
> http://mail.python.org/mailman/listinfo/python-win32
>



More information about the Python-win32 mailing list