Exception: Invalid object array with comtypes

2019-07-28 19:18发布

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条回答
forever°为你锁心
2楼-- · 2019-07-28 20:08

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!

查看更多
登录 后发表回答