【问题标题】:How to construct an objectlist for COM?如何为 COM 构造对象列表?
【发布时间】:2013-02-18 17:49:20
【问题描述】:

这是一个以前用VBA写的真实项目。

我想将其移至 Python 并使用“带有 Python 的 AutoCAD 的 ActiveX 自动化脚本”方法。这是我的代码:

# -*- coding: utf-8 -*-

from pyautocad import Autocad, APoint, aDouble


acad = Autocad(False,  True)
acad.prompt("Hello, Autocad from Python\n")
print acad.doc.Name

xx = acad.model.AddCircle(APoint(0, 0),  10)
print(xx)
yy = acad.model.Add3Dpoly(aDouble([0,  0,  0,  10,  10,  10,  30,  20,  30,  0,  0,  0]))
print(yy.ObjectName)
print(yy.PlotStyleName)

# How to contruct an objectlist for AddRegion?
#regions = acad.model.AddRegion([yy])
#acad.model.AddExtrudedSolid(regions[0], 20, 0)

我的问题是,如何为AddRegion 构造一个对象列表?也许comtypes 有一些关于 VARINT 的话题。 COM之类的我真的没有经验……

【问题讨论】:

  • 不幸的是,我还没有找到如何正确地将对象数组传递给 Autocad。 Related issue
  • 直接从 COM 调用函数的简单解决方法是使用acad.SendCommand('xxxx')。 pyCOM 传递字符串没有问题(数组是你遇到麻烦的地方)。这可以让你从 python 做一些自动化,但并不是每个 AutoCAD 函数都有一个简单的命令行界面,所以这是一个有限的解决方案。

标签: python com automation activex autocad


【解决方案1】:

让一切正常工作可能比看起来应该做的要多。使用python读取数据;还不错。写入数据,有点棘手。休闲用户/初学者;被警告你会进入什么。


你可能需要什么

如果您熟悉 autolisp,它会大有帮助,因为它只是工作得更好(在这种情况下),记录得更好,集成得更好,......而且您可能需要它来挤奶“未知/隐藏/未记录” python没有告诉你的信息。 (参见 vlax-vla- 系列 lisp 函数)。

接下来,您需要命令行中的 win32com make_py 和 gen_py 脚本,或者您可以使用 win32com.client.gencode,同时主要使用 python。

准备好在视觉上解析非常丑陋的文本(我什至没有在谈论 lisp =] )。做好失败的准备,并为找出原因而兴奋。

其中大部分与 COM 变体有关。然后你会得到一些奇怪的东西,比如 Variant-Variant-Arrays。如果您查看 win32com.client.pythoncom,您会注意到所有数据类型都映射为整数。 (例如 VT_BOOL 为 11)。


细枝末节

下次您尝试 ModelSpace.AddCircle 时,请注意您得到的调试输出; 所有传递给 InvokeTypes 的参数都是您需要注意的...(取自我的 make-py 输出的 Autocad 注册接口

def AddLine(self, StartPoint=defaultNamedNotOptArg, EndPoint=defaultNamedNotOptArg):       
    ret = self._oleobj_.InvokeTypes(
                        1581, LCID, 1, (9, 0), ((12, 1), (12, 1)),StartPoint, EndPoint)
    if ret is not None:
        ret = Dispatch(ret, u'AddLine', '{DF524ECB-D59E-464B-89B6-D32822282778}'

这会准确告诉您 win32com THINKS 它想要哪些 COM 类型,因此请确保您至少匹配它。

我发现许多输入函数实际上被记录和调用是错误的(我在反复使用 AutoLisp 之后才知道这一点)。我们在上面看到的外部值为 1581(类似于类名,而不是真正的数据类型),然后是基本上表示 (DISPATCH, EMPTY) 的元组strong>:(9,0),然后是 VT_VARIANTS:((12,1),(12,1)) 的数组。

COM 所期望的通常缺少一个外包装,并且由于某种原因 make-py 没有意识到这一点。如果你通过大量的 AutoLisp vlax- 废话,你会注意到它们是一个额外的包装器。我相信它要么是 VARIANT_ARRAY,要么是字面意义上的 VARIANT-VARIANT-ARRAY(四元指针或其他东西)。代码为 (vt_array=8192, vt_variant=12)。

对不起,我不记得细节了,但我相信阅读 ((12,1),(12,1)) 的部分应该变成 (8192, 12, ( (12,1),(12,1))),或类似的东西。即使您确实弄清楚了它应该是什么,我也不确定它们是否可以快速解决。从 AutoCAD 2010 开始,对我来说,这意味着要通过非常大的 gen_py 输出,找到我真正想要的功能,并手动更改 InvokeTypes() 调用以匹配 COM 的预期。

在那之后一切都按预期进行。


可能的解决方法

COM 很丑。如果您是 python 新手,但在 AutoCAD 方面经验不足(这意味着您想做一些相当高的自动化操作),请远离 python->win32com->AutoCAD 管道。使用 LISP。尽管这让我很痛苦,但你最终会编写如此多的 LISP 测试用例和调试器来伴随你的 python 痛苦,你还不如提交。

  • Ironpython 和 .NET
    • 我相信这个接口通常比 COM 更受支持
  • Visual Studio 专业版 (2008+)
    • 我从未使用过官方的 VS-Pro 工具(我使用过 PythonWIN 和 MINGW),我不确定是否提供了任何额外的魔法来改变 win32com 处理 AutoCAD 的方式。我知道官方的 AutoCAD ARX 扩展在 Studio 项目中提供了它们的源代码。最坏的情况是,您手头有实际的文档,这就是整个 python-AutoCAD 主题受到污染的地方。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-07
    相关资源
    最近更新 更多