Найти - Пользователи
Полная версия: Вопрос о COM/Automation
Начало » Python для экспертов » Вопрос о COM/Automation
1
Andrey Skobeldin
Есть работающий фрагмент примера на visual basic:
—–8<——
Dim TopApp As TopSolid.Application
Dim TopDoc As TopSolid.DocumentDesign

Set TopApp = New TopSolid.Application

' create a new document *.top
Set TopDoc = TopApp.Documents.Add(“top”)

Dim TopCircle As TopSolid.Curve

' Create a basic circle
Set TopCircle = TopDoc.Curves.AddBasicCircle(0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01)
—–8<——
Подскажите пожалуйста, как аналогично это сделать на Питоне?
С применением comtypes я получаю TopApp и TopDoc, но уж никак не TopDoc.Curves. Мне кажется, что дело в виде связывания.
reclosedev
Код? Traceback, ошибки?
Andrey Skobeldin
Код был примерно такой:
from comtypes.client import CreateObject
TopApp = CreateObject('TopSolid.Application')
TopApp.Visible = True
TopDoc = TopApp.Documents.Add('top')
TopCircle = TopDoc.Curves.AddBasicCircle(0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01)
#
# Тут выскакивает ошибка по поводу отсутствия свойства Curves в TopDoc 
Однако, в документации по api этой системы нашел такие строки:

Many TopSolid objects support more than one interface.

For example, design documents (“*.top” files) are accessible through DocumentDesign objects, which support two interfaces, IDocument for general document handling, and IDocumentDesign for design document specific functionalities.

To do so, TopSolid implements what is known in the COM (Component Object Model) world as “multiple dual interfaces”.

This means that one single object may implement several (what is known as “IDispatch”) interfaces, and one will need to switch from one to another to access the full set of available methods and properties.

Unlike VB, script languages cannot manage objects with multiple interfaces directly.

To compensate for this limitation, TopSolid uses a special mechanism, called “DISPID encoding”, that allows script languages to have access to methods and properties of objects that have multiples interfaces, with the only restriction that the name of the method/property must be unique among all the interfaces implemented in the object.

Usually, this will be the case, but if it is not, then it is the method/property of the first interface that will be called (the ordered list of the interfaces implemented by each object is given in the object description page).

Я не специалист в области COM, но мне кажется что можно работать с этими множественными интерфейсами и на Питоне. Если бы хоть кто из спецов примерчик для аналогичной задачи показал ;)
reclosedev
С TopSolid не знаком, но в Autocad например, при получении списка объектов возвращаются IAcadEntity вместо конкретных IAcadLine и т.п.

Для того чтобы получить нужный интерфейс, есть несколько вариантов
С Автокадом всегда работает такой:
obj = comtypes.client.GetBestInterface(obj)

Но может потребоваться явное преобразование:
TopDoc = TopDoc.QueryInterface(comtypes.gen.TopSolid.IDocumnetOrSomethingElse)  # нужно заменить на правильный
Andrey Skobeldin
Как то так получилось получить Curves:
curves = win32com.client.CastTo(doc, 'ICurves')
#curves
#<win32com.gen_py.TopSolid 6.10 Type Library.ICurves instance at 0x23988184>
c1 = curves.AddBasicLine(0, 0, 0, 0.3, 0, 0)
# ругается
# com_error: (-2147352573, 'Член группы не найден.', None, None)
Фрагмент сгенерированного makepy файла:
	# Result is of type ICurve
	def AddBasicLine(self, Sx=defaultNamedNotOptArg, Sy=defaultNamedNotOptArg, Sz=defaultNamedNotOptArg, Tx=defaultNamedNotOptArg
			, Ty=defaultNamedNotOptArg, Tz=defaultNamedNotOptArg):
		'Add a basic line'
		ret = self._oleobj_.InvokeTypes(3, LCID, 1, (9, 0), ((5, 1), (5, 1), (5, 1), (5, 1), (5, 1), (5, 1)), Sx, Sy, Sz, Tx, Ty, Tz)
		if ret is not None:
			ret = Dispatch(ret, u'AddBasicLine', '{2EF8935B-964A-482E-AA8D-853517AADBBE}')
		return ret
Видимо дело в передаче аргументов функции?
Попробовал упаковать аргументы в array (что работало в Автокаде) - выдает TypeError: float() argument must be a string or a number
reclosedev
Так вы comtypes используете или win32com? Лучше что-то одно, и по мне - это comtypes.

Andrey Skobeldin
curves = win32com.client.CastTo(doc, ‘ICurves’)
Если doc - это документ, то мне кажется, что его приводить надо к IDocumentDesign,
doc = doc.QueryInterface(comtypes.gen.TopSolid.IDocumentDesign)
а потом уже
doc.Curves.AddBasicLine(0, 0, 0, 0.3, 0, 0)

Andrey Skobeldin
Попробовал упаковать аргументы в array (что работало в Автокаде) - выдает TypeError: float() argument must be a string or a number
В Автокаде это нужно потому что методы принимают массив чисел определенного типа (double), а здесь, судя по документации, передается все правильно.
Andrey Skobeldin
Да, сработало! Благодарю за помощь!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB