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

wccppp wccppp at gmail.com
Thu Feb 2 09:23:26 CET 2006


Mark,

Thank you for your suggestion.  If I can do something like this:
v = Variant(VT_DOUBLE, (1.0, 2.0, 3.0))
ms.AddPoint(v)
That would be great!  But I am not sure how to write the "Variant" class as
you suggested.  I bought your book "Python Programming on Win32" beause I
wanted to automate windows applications, mostly AutoCAD, with python.
Unfortunately the usage of InvokeTypes() was not covered in your book.  Can
you give a little more detailed guide on how to write this "Variant" class?
Thank you.  - wcc



On 1/26/06, Mark Hammond <mhammond at skippinet.com.au> wrote:
>
> 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
> >
>
> _______________________________________________
> Python-win32 mailing list
> Python-win32 at python.org
> http://mail.python.org/mailman/listinfo/python-win32
>



--

Regards,
- wcc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/python-win32/attachments/20060201/a8c9dc83/attachment.htm 


More information about the Python-win32 mailing list