2 votes

Comment construire une liste d'objets pour COM?

Ceci est un vrai projet écrit en VBA auparavant.

Je veux le transférer en Python et utiliser la méthode 'Scripts d'automatisation ActiveX pour AutoCAD avec Python'. Ceci est mon code :

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

from pyautocad import Autocad, APoint, aDouble

acad = Autocad(False,  True)
acad.prompt("Bonjour, Autocad depuis 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)

# Comment construire une liste d'objets pour AddRegion?
#regions = acad.model.AddRegion([yy])
#acad.model.AddExtrudedSolid(regions[0], 20, 0)

Ma question est, comment construire une liste d'objets pour AddRegion? Peut-être que comtypes a quelque sujet sur VARINT. Je n'ai vraiment aucune expérience en COM et ainsi de suite...

1voto

user2097818 Points 867

Le faire fonctionner correctement peut être plus compliqué que prévu. Lire des données en utilisant le python ; pas si mal. Écrire des données, un peu plus délicat. Utilisateur occasionnel / Débutants; soyez avertis de ce dans quoi vous vous engagez.


Ce dont vous aurez probablement besoin

Il est d'une grande aide si vous êtes familier avec autolisp,car cela fonctionne tout simplement mieux (dans ce cas), est mieux documenté, et s'intègre mieux,... et vous en aurez probablement besoin pour extraire des informations 'inconnues/cachées/non documentées' que le python ne vous dit pas (voir les fonctions lisp de la série vlax- et vla-).

Ensuite, vous avez besoin des scripts win32com make_py et gen_py à partir de la ligne de commande, ou vous pouvez utiliser win32com.client.gencode tout en restant principalement dans le python.

Soyez prêt à analyser visuellement du texte très laid (et je ne parlais même pas de lisp =] ). Soyez prêt à échouer, et soyez enthousiaste à l'idée de découvrir pourquoi.

La plupart de cela a à voir avec les COM-Variants. Et ensuite vous obtenez des choses étranges comme les Variant-Variant-Arrays. Si vous consultez win32com.client.pythoncom, vous remarquerez que tous les types de données sont mapés en entiers. (VT_BOOL est par exemple égal à 11).


Les Détails Techniques

La prochaine fois que vous tenterez un ModelSpace.AddCircle, faites attention à la sortie de débogage que vous obtenez ; Les paramètres passés à InvokeTypes sont ceux que vous devez surveiller... (ceci est extrait de ma sortie make-py pour les Interfaces Enregistrées d'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}'

Cela vous indique exactement quels types de COM win32com PENSE qu'il veut, alors assurez-vous au moins de correspondre à cela.

J'ai constaté que de nombreuses fonctions d'entrée sont en fait documentées et invoquées de manière incorrecte (j'ai appris cela après beaucoup d'allers-retours avec Autolisp). Ce que nous voyons ci-dessus a une valeur de 1581 à l'extérieur (qui est quelque chose comme un nom de classe, pas vraiment un type de données), puis un tuple qui dit fondamentalement (DISPATCH, EMPTY) : (9,0), et ensuite un tableau de VT_VARIANTS : ((12,1),(12,1)).

Il manque généralement un enrobage extérieur que COM attendait, et pour une raison quelconque, make-py ne se rend pas compte de cela. Si vous parcourez l'absurde nonsense vlax- d'Autolisp, vous remarquerez qu'il y a un enrobage supplémentaire autour de cela. Je crois que c'est soit un VARIANT_ARRAY, soit littéralement, un VARIANT-VARIANT-ARRAY (pointeur quadruple ou quelque chose). Les codes pour cela sont (vt_array=8192, vt_variant=12).

Désolé, je ne me souviens pas des détails exacts, mais je crois que la partie qui lit ((12,1),(12,1)) devrait devenir (8192, 12, ((12,1),(12,1))), ou quelque chose comme cela. Même une fois que vous avez compris ce que cela devrait être, je ne suis pas sûr s'il y a une solution rapide. Au moment d'AutoCAD 2010, pour moi, cela signifiait passer par la sortie gen_py très volumineuse, trouver les fonctions que je voulais vraiment, et changer manuellement l'appel InvokeTypes() pour correspondre à ce que COM attendait.

Tout a fonctionné simplement comme prévu après cela.


Solutions Possibles

COM est laid. Si vous êtes nouveau dans le python, mais semi-expérimenté dans AutoCAD (ce qui signifie que vous voulez faire un peu d'automatisation assez poussée), éloignez-vous du pipeline python->win32com->AutoCAD. Utilisez LISP. Autant cela me fait mal de le dire, vous allez finir par écrire tellement de LISP test cases et débogueurs pour accompagner vos douleurs python, autant vous engager directement.

  • Ironpython et .NET
    • Je crois que cette interface est bien plus supportée que COM en général
  • Visual Studio Professional (2008+)
    • Je n'ai jamais utilisé les outils officiels de VS-Pro (j'ai utilisé PythonWIN et MINGW), je ne suis pas sûr s'il y a une magie supplémentaire fournie qui changerait la manière dont win32com gère AutoCAD. Je sais que les extensions ARX officielles d'AutoCAD fournissent leur source dans un projet Studio. Dans le pire des cas, vous auriez une documentation réelle à portée de main, ce qui rend ce sujet entier du python-AutoCAD entaché.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X