Exception: Invalid object array with comtypes

不羁岁月 提交于 2019-12-11 05:46:46

问题


I try to implement a simple copy operation between two Autocad documents via COM in Python.

from pyautocad import Autocad, APoint
from comtypes.client import GetBestInterface
# Get acad application
acad = Autocad(create_if_not_exists=True)
# Create a new document
doc1 = GetBestInterface(acad.Application.Documents.Add())
# add a circle in this document and make it visible
circle = GetBestInterface(doc1.ModelSpace.AddCircle(APoint(0.0, 0.0), 1.0))
doc1.Application.ZoomExtents()
# create another document
doc2 = GetBestInterface(acad.Application.Documents.Add())
# and copy the circle to the new document
doc1.CopyObjects([circle], doc2.ModelSpace)

This throws:

Traceback (most recent call last):
  File "copy_bug.py", line 13, in <module>
    doc1.CopyObjects([circle], doc2.ModelSpace)
  File "Anaconda2\lib\site-packages\comtypes\__init__.py", line 655, in call_with_inout
    rescode = func(self_, *args, **kw)
_ctypes.COMError: (-2145320837, None, (u'Invalid object array', u'AutoCAD.Application', u'C:\\Program Files\\Autodesk\\AutoCAD 2015\\HELP\\OLE_ERR.CHM', -2145320837, None))

Same thing may be accomplished in VBA with:

Dim doc1 As AcadDocument
Set doc1 = ThisDrawing.Application.Documents.add
Dim pt(0 To 2) As Double
pt(0) = 0#: pt(1) = 0#: pt(2) = 0#
Dim circ As AcadCircle
Set circ = doc1.ModelSpace.AddCircle(pt, 1)

ThisDrawing.Application.ZoomExtents

Dim doc2 As AcadDocument
Set doc2 = ThisDrawing.Application.Documents.add

Dim arry(0 To 0) As AcadEntity
Set arry(0) = circ
doc1.CopyObjects arry, doc2.ModelSpace

I tried numpy arrays, I tried casting to the IDispatch interface, the IAcadEntity interface and IAcadObject with no success (probably a silly attempt).

circle = circle.QueryInterface(IAcadEntity)

I also tried to look inside site-packages\comtypes\automation.py but that's above my pay grade. Setting the self.vt to VT_ARRAY | VT_DISPATCH in _set_value does no good but I suspect that the problem is along those lines because, if we change Dim arry(0 To 0) As AcadEntity to Dim arry(0 To 0) As Variant the VBA example will also throw Invalid object array.


I should mention that I un-commented two lines in site-packages\comtypes\automation.py:

# These are not yet implemented:
POINTER(IUnknown): VT_UNKNOWN,
POINTER(IDispatch): VT_DISPATCH,

So .... help?!


回答1:


Meanwhile, there are some ugly hacks like:

Dim doc1 As AcadDocument
Set doc1 = ThisDrawing.Application.Documents.add
Dim pt(0 To 2) As Double
pt(0) = 0#: pt(1) = 0#: pt(2) = 0#
Dim circ As AcadCircle
Set circ = doc1.ModelSpace.AddCircle(pt, 1)

ThisDrawing.Application.ZoomExtents
Dim EXTMIN As Variant: EXTMIN = ThisDrawing.GetVariable("EXTMIN")
Dim EXTMAX As Variant: EXTMAX = ThisDrawing.GetVariable("EXTMAX")

Call ThisDrawing.SendCommand( _
    "_SELECT Window " & CStr(EXTMIN(0)) & "," & CStr(EXTMIN(1)) & _
    " " & CStr(EXTMAX(0)) & "," & CStr(EXTMAX(1)) & vbNewLine)
doc1.SendCommand ("_COPYBASE 0,0" & vbNewLine)

Dim doc2 As AcadDocument
Set doc2 = ThisDrawing.Application.Documents.add
doc2.SendCommand ("_PASTECLIP 0,0" & vbNewLine)

from pyautocad import Autocad, APoint
from comtypes.client import GetBestInterface

acad = Autocad(create_if_not_exists=True)
doc1 = GetBestInterface(acad.Application.Documents.Add())
circle = GetBestInterface(doc1.ModelSpace.AddCircle(APoint(0.0, 0.0), 1.0))
doc1.Application.ZoomExtents()

EXTMIN = doc1.GetVariable("EXTMIN")
EXTMAX = doc1.GetVariable("EXTMAX")

doc1.SendCommand( "_SELECT Window %f,%f %f,%f\n\r" % (
    EXTMIN[0], EXTMIN[1], EXTMAX[0], EXTMAX[1]))
doc1.SendCommand ("_COPYBASE 0,0\n\r")

doc2 = GetBestInterface(acad.Application.Documents.Add())
doc2.SendCommand ("_PASTECLIP 0,0\n\r")

(of course you can create a selection set but you cannot make an selection set active; that would be madness)

Please post a better answer!



来源:https://stackoverflow.com/questions/37757823/exception-invalid-object-array-with-comtypes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!