Базовые интерфейсы IKompasDocument1

Автор SkippeRR, 11.08.20, 00:05:25

« предыдущая - следующая »

0 Пользователей и 1 гость просматривают эту тему.

SkippeRR

Здравствуйте! Подскажите пожалуйста новичку. Как получить доступ к базовому интерфейсу IKompasDocument1.
Язык Python (я совсем новичок)
Прошу с примером кода т.к. в разделе SDK я не разобрался (там пишут следующие, но как применить кусок этого кода до меня не дошло)

kompasDoc = KomApp.ActiveDocument
doc2D = kompasDoc._oleobj_.QueryInterface(KAPI7.NamesToIIDMap['IDrawingDocument'], pythoncom.IID_IDispatch)
doc2D = API7.IDrawingDocument(doc2D)

Спасибо, буду рад любому объяснению!

Вират Лакх

11.08.20, 05:08:34 #1 Последнее редактирование: 11.08.20, 05:30:54 от Вират Лакх Причина: Посмотреть методы и свойства полученного интерфейса
ЦитироватьКак получить доступ к базовому интерфейсу IKompasDocument1
Где написано, что он базовый?
В SDK сказано: Интерфейс является дополнительным к интерфейсу документа IKompasDocument. Ин­терфейс можно получить посредством вызова метода IUnknown::QueryInterface (const GUID far& iid, void** pif).

По приведенному примеру из SDK.
Здесь KomApp - это интерфейс приложения КОМПАС-3D - IApplication, то есть:
KomApp = Dispatch('Kompas.Application.7')
Но лучше называть вещи своими именами. Большую I заменяем на маленькую i: iApplication

От него получаем текущий активный документ:
kompasDoc = KomApp.ActiveDocument
А чтобы выглядело по-людски и читалось нормально:
iKompasDocument = iApplication.ActiveDocument # Получили интерфейс IKompasDocument
Вот он Базовый класс документов КОМПАС.

Вот этой ерундой я не заморачиваюсь:
doc2D = kompasDoc._oleobj_.QueryInterface(KAPI7.NamesToIIDMap['IDrawingDocument'], pythoncom.IID_IDispatch)
А использовать второй вариант:
doc2D = API7.IDrawingDocument(doc2D)
Результат один и тот же.

В обоих вариантах присутствуют некие KAPI7 и API7 - это одно и то же, только по-разному названы.
API7 - это модуль .py, полученный из библиотеки типов kApi7.tlb. В нём содержатся классы.
Получить его можно так:
API7 = gencache.EnsureModule('{69AC2981-37C0-4379-84FD-5DD2F3C0A520}', 0, 1, 0)
Или, имея ранее полученный файл API7.py, импортировать его:
import API7

Простые объекты поддерживают только один интерфейс. Сложные - несколько интерфейсов.
Объект один, а интерфейсов несколько. Как многогранник.
Отсюда смотрим на документ компаса со стороны IKompasDocument1:
iKompasDocument1 = API7.IKompasDocument1(iKompasDocument)
И видим там методы и свойства документа с точки зрения IKompasDocument1.

Итого код может быть таким:
from win32com.client import Dispatch, gencache
API7 = gencache.EnsureModule('{69AC2981-37C0-4379-84FD-5DD2F3C0A520}', 0, 1, 0)
iApplication = Dispatch('Kompas.Application.7')
iKompasDocument = iApplication.ActiveDocument
iKompasDocument1 = API7.IKompasDocument1(iKompasDocument)

Upd.
Как посмотреть методы интерфейсов:
print(dir(iApplication))
print(dir(iKompasDocument1))

Как посмотреть свойства интерфейсов:
def printprop(i):
   for prop in sorted(i._prop_map_get_):
      print(prop, getattr(i, prop))

printprop(iApplication)
printprop(iKompasDocument1)

SkippeRR

Вират Лакх, огромнейшее спасибо за подробный и развернутый ответ, нигде на форуме я не мог найти ничего подобного, еще раз спасибо!

Tallin

А объясните пожалуйста по человечески что вообще такое интерфейс объекта.


Вират Лакх

COM (англ. Component Object Model «модель компонентного объекта»; произносится как [ком]) -- это технологический стандарт от компании Microsoft, предназначенный для создания программного обеспечения на основе взаимодействующих компонентов объекта, каждый из которых может использоваться во многих программах одновременно.
COM - это технология, позволяющая объектам взаимодействовать, несмотря на границы процесса или машины, так же легко, как и объектам внутри одного процесса. COM обеспечивает такое взаимодействие, определяя, что единственный путь управления данными, ассоциированными с объектом, лежит через интерфейс объекта. Термин «интерфейс», о котором речь пойдет чуть ниже, означает реализацию в коде COM-совместимого двоичного интерфейса, ассоциированного с объектом.
COM-объект можно сравнить с объектом в понимании С++, VB или Java. Объект СОМ - это некоторая сущность, имеющая состояние и методы доступа, позволяющие изменять это состояние. СОМ-объекты можно создавать прямым вызовом специальных функций, но напрямую уничтожить его невозможно.
Так, в COM присутствует понятие класса. Класс в COM носит название CoClass.
CoClass - это класс, поддерживающий набор методов и свойств (один или более), с помощью которых можно взаимодействовать с объектами этого класса. Такой набор методов и свойств называется интерфейсом (Interface).
Каждый CoClass имеет два идентификатора - один из них, текстовый, называется ProgID и предназначен для человека, а второй, бинарный, называется CLSID.
CLSID является глобально уникальным идентификатором (GUID). GUID имеет размер 128 бит и уникален в пространстве и времени. Его уникальность достигается путем внедрения в него информации об уникальных частях компьютера, на котором он был создан, таких, как номер сетевой карты, и времени создания с точностью до миллисекунд. С помощью CLSID можно точно указать, какой именно объект требуется. Тип данных GUID применяется и для идентификации COM-интерфейсов. В этом случае он называется IID. Сгенерировать новое значение типа GUID можно с помощью API-функции Win32 CoCreateGuid. На практике использовать эту функцию приходится не часто, так как современные средства разработки полностью автоматизируют эту задачу, а VB вообще скрывает от программиста такие тонкости, как работу с CLSID и IID.
Для создания экземпляра объекта используется CLSID. Если имеется только ProgID CoClass'а или CLSID в строковом виде ("{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} ", где X - шестнадцатеричная цифра), то CLSID можно получить, вызвав функцию CLSIDFromString. Для случая с ProgID информация о CoClass'е должна содержаться в реестре машины, на которой производится вызов функции. В реестр информация заносится автоматически при регистрации объекта (во время процедуры инсталляции или при компиляции).
Программист никогда не взаимодействует с объектом и его данными напрямую. Для этого используются интерфейсы объектов.
В понимании СОМ интерфейс - это контракт, состоящий из списка связанных прототипов функций, чье назначение определено, а реализация - нет. Эти прототипы функций эквивалентны абстрактным базовым классам С++, то есть классам, имеющим только виртуальные методы, описания без реализации. Определение интерфейса описывает функции-члены интерфейса, называемые методами, типы их возвращаемого значения, число и типы их параметров, а также описывает, что они, собственно, должны делать. Напрямую с интерфейсом не ассоциировано никакой реализации.
Реализация интерфейса (interface implementation) - это код, который программист создает для выполнения действий, оговоренных в определении интерфейса. Реализации интерфейсов, помещенные в COM-библиотеки или exe-модули, могут использоваться при создании объектно-ориентированных приложений. Разумеется, программист может игнорировать эти реализации и создать собственные. Интерфейсы ассоциируются с CoClass'ами. Чтобы воспользоваться реализацией функциональности интерфейса, нужно создать экземпляр объекта соответствующего класса, и запросить у этого объекта ссылку на соответствующий интерфейс.
Например, для описания взаимодействия с некоторым абстрактным стеком можно определить интерфейс IStack (в COM стало доброй традицией начинать названия интерфейсов с «I»). Этот интерфейс может содержать два метода, скажем, Push и Pop. Вызов метода Pop возвращает значения, заложенные до этого методом Push в стек, но в обратном порядке. Это определение интерфейса не говорит, как функции будут реализованы в коде. Один программист может реализовать стек как массив, а методы Push и Pop - как методы доступа к этому массиву. Другому же взбредет в голову использовать связанный список и соответствующую реализацию методов. Независимо от конкретной реализации методов, представление в памяти указателя на интерфейс IStack, и, соответственно, его использование клиентом полностью специфицируется определением интерфейса.
Простые объекты могут поддерживать только один интерфейс. Более сложные объекты, как правило, поддерживают несколько интерфейсов. Это свойство позволяет реализовать полиморфизм на уровне компонентной модели.
Слово «интерфейс» используется в COM не в том смысле, что в С++. Интерфейс в С++ ссылается на все функции, поддерживаемые классом. COM-интерфейс ссылается на предварительно оговоренную группу связанных функций, реализуемых COM-классом, но не обязательно на ВСЕ функции, поддерживаемые классом.
СОМ поддерживает реализацию нескольких интерфейсов в одном объекте, и поэтому требует отдельного определения класса объекта (см. "CoClass").
Экземпляр «реализации интерфейса» на самом деле является указателем на массив указателей на методы (таблицу функций, ссылающуюся на реализации всех методов, определенных в интерфейсе, также называемую виртуальной таблицей - VTbl). Объекты с несколькими интерфейсами могут предоставлять указатели на несколько таблиц функций. Любой код, содержащий указатель, через который он имеет доступ к массиву, может вызывать методы этого интерфейса.
Все это очень длинно и косноязычно, так что указатель на таблицу функций интерфейса, который должен иметь другой объект для вызовов методов этого интерфейса, называют просто указателем на интерфейс.
Интерфейс имеет свое имя. Как мы уже говорили, каждый интерфейс - это неизменяемый контракт, во время исполнения определяемый по глобально уникальному идентификатору интерфейса, IID. IID, это особая разновидность GUID, позволяет клиентам точно и без ненужных сложностей, узнать у объекта, поддерживает ли он некоторый интерфейс. Идентификация интерфейсов по IID решает проблему неуникальности имен интерфейсов. Это необходимо, поскольку разработка COM-объектов ведется одновременно во всех частях света, и никто не гарантирует, что объекты с одноименными, но разными интерфейсами не встретятся в один прекрасный момент на каком-нибудь компьютере.
Все интерфейсы должны быть унаследованы от интерфейса IUnknown. IUnknown содержит три жизненно важных для COM метода: QueryInterface, AddRef и Release. Все COM-объекты должны реализовать интерфейс IUnknown, поскольку он обеспечивает возможность получать поддерживаемые объектом интерфейсы с помощью QueryInterface, и управлять сроком жизни объекта через AddRef и Release.
Высокоуровневые средства разработки (такие, как VB) полностью скрывают реализацию IUnknown, облегчая тем самым работу программиста.
Чтобы воспользоваться функциональностью COM-объекта, нужно создать его экземпляр (instance).