4.3.1.1. Загальна характеристика COM
Одним з ключових досягнень Windows по праву вважається багатокомпонентна модель об'єктів (Component Object Model, COM). Модель COM описує спосіб взаємодії програм будь-якого типу. Програма-сервер (сервер COM) надає в розпорядження оточуючих власні служби, а програма-клієнт (клієнт COM) користується послугами доступних служб. Взаємодіючі COM-об'єкти можуть функціонувати як в рамках одного і того ж процесу, так і в різних процесах, в тому числі що перебігають на різних машинах під керуванням різних операційних систем. COM - це одночасно і специфікація (визначає порядок створення взаємодіючих між собою додатків), і реалізація (в формі стандартного набору функцій API). Крім того, COM - це незалежна від платформи, розподілена об'єктно-орієнтована система, призначена для створення взаємодіючих програмних компонентів.
З точки зору стороннього спостерігача створюється засобами COM програмний компонент являє собою чорний ящик, що володіє наступними характеристиками:
1. Легкість підключення до операційної системи.
3. Простота інтеграції до складу програмного забезпечення.
4. Універсальний спосіб звернення до методів і властивостей з будь-якого сучасного мови програмування.
Корпорація Microsoft стандартизувала як спосіб представлення COM - об'єкта в пам'яті комп'ютера, так і особливості ідентифікації методів і властивостей цього об'єкта. Тому в офіційній документації Microsoft (MSDN) при описі COM неодноразово згадується про те, що COM-модель відповідає бінарним (іншими словами, універсального) стандарту.
На перший погляд чорний ящик COM вельми схожий бібліотеку DLL.
Як і COM, DLL дозволяє багаторазово використовувати свій код, легко підключатися до ОС і інтегруватися в програмне забезпечення. Але що динамічно підключається не в змозі гарантувати, що експортуються нею функції без будь-яких обмежень можуть бути викликані засобами іншої мови програмування. Крім того, при роботі c DLL ми стикаємося з рядом обмежень, пов'язаних з місцем її розміщення: бібліотека повинна розташовуватися або в строгому переліку каталогів, або обов'язково прописуватися в системних шляхах. Ще більш складна задача - завантаження DLL з іншого комп'ютера. На відміну від DLL, модель COM забезпечує універсальний спосіб завантаження своїх об'єктів незалежно від місця їх розміщення.
З перших кроків вивчення COM важливо зрозуміти, що це не черговий об'єктно-орієнтована мова програмування зі своїм синтаксисом, семантикою і деталями реалізації. Правильніше говорити про COM як про стандарт, який визначає модель взаємодії між об'єктами.
В інтересах клієнтських і серверних додатків COM-моделі активно працює бібліотека COM (COM Library). Фізично бібліотека COM являє собою набір виконуваних файлів і динамічно підключаються бібліотек. Вона здатна:
1. Надавати послуги деякого набору функцій API, що полегшують розробку додатків COM. Наприклад, для клієнтських додатків призначені методи, що створюють об'єкти. Для додатків серверів в бібліотеці передбачено кошти демонстрації їх COM-об'єктів.
2. Генерувати унікальний ідентифікатор об'єкта, здійснювати пошук необхідного об'єкта за його ідентифікатором.
3. Проводити виклик віддалених процедур, якщо сервер COM розміщений на іншому комп'ютері.
4. Керувати розподілом пам'яті в інтересах взаємодіючих процесів і контролювати звільнення пам'яті.
За існуючою домовленістю імена всіх методів Win32 API бібліотеки COM починаються із префікса «Co», наприклад CoCreateGuid (), CoCreateInstance (), CoUn- initialize () і т. П.
4.3.1.2. Елементи COM-додатки
Розробник стандартного COM-додатки в будь-якому випадку зіткнеться з двома його елементами:
Сервер COM являє собою окремий модуль, реалізований у вигляді самостійного виконуваного EXE-файлу або файлу динамічної бібліотеки DLL.
Моделлю COM передбачено два різновиди сервера: внутрішній і зовнішній.
Розглянемо класи VCL, поставлені на службу технології COM.
До складу COM-сервера як мінімум входять:
1. Один - єдиний екземпляр класу TcomServer, інкапсулює сам COM-сервер. Підхід до цього об'єкту забезпечує створювана при запуску сервера глобальна змінна ComServer.
2. Опис COM-об'єкта (або декількох об'єктів), прототипом якого є клас TComObject.
3.Фабріка класу (по одній на кожен тип COM-об'єкта). Основою фабрики класу є клас TComObjectFactory. Єдине завдання фабрики класу полягає в створенні інших об'єктів - екземплярів класу TComObject.
З виходом чергової версії бібліотеки не треба оновлювати все своє програмне забезпечення.
В COM-моделі процесом створення нового об'єкта відає не середовище програмування і навіть не сам об'єкт, а третя (в якійсь мірі нейтральна) сторона - фабрика класу (class factories). Саме фабрика цілком і повністю відповідає за розподіл пам'яті для майбутнього COM-об'єкта, і при цьому, як би це нам не здалося парадоксальним, про подробиці побудови цього об'єкта не має ні найменшого уявлення.
Для кожного окремого COM-класу призначена окрема фабрика.
Для створення нового екземпляра класу фабрика користується шаблоном класу, або фабричним зразком (factory pattern).
Фабричний зразок - це особливий клас, застосовуваний для створення екземпляра іншого класу.
Завдяки «фабричному» підходу процес створення нового об'єкта відділяється від особливостей його реалізації.
Обслуговуванням фабрик відає менеджер фабрик - об'єкт класу TComClass - Manager. Примірник менеджера створюється автоматично і доступний в додатку COM - сервера завдяки глобальній змінній ComClassManager.
Клієнт COM користується послугами сервера, але не має ні найменшого поняття про особливості його реалізації. Доступ клієнта до служб впровадженого в сервер COM-об'єкта здійснюється тільки через інтерфейси цього об'єкта; це ключова особливість всієї COM-моделі. Отримавши покажчик на інтерфейс, клієнтське додаток набуває право виклику методів об'єкта.
4.3.1.3. COM - об'єкт
В основі багатокомпонентної моделі лежить поняття COM-об'єкта.
Фізично COM-об'єкт являє собою сукупність даних і методів, які керують цими даними. Структура COM-об'єкта суттєво відрізняється від кнопок і рядків введення, звичних нам по бібліотеці VCL. Ключова відмінність COM від знайомого нам об'єкта Delphi в тому, яким чином COM-об'єкт надає доступ до своїх даних.
Структура COM-об'єкта матеріалізує ідею казки про Кощія Безсмертного. Пам'ятайте: смерть в голці, голка в яйці, яйце в качці, качка в зайці, заєць в скрині, скриня на дубі. Невідомо, читали в Microsoft російські народні казки чи ні, але проектуючи COM-об'єкт, програмісти корпорації впевнено пішли второваним Кощієм шляху - прямого доступу до даних COM- об'єкта ззовні в принципі не існує. Кожне поле об'єкта приховано в його надрах і може обслуговуватися тільки методами COM-об'єкта. Методи об'єкта також особливої комунікабельністю не відрізняються; вони упаковані так глибоко, що доступні лише через свої покажчики.
Мал. 6. Модель COM-об'єкта
Отримавши доступ до обов'язково присутнього інтерфейсу IUnknown, програма або будь-який інший об'єкт відразу може звернутися до функції QueryInterface () і дізнатися про всі інші наявних у цього об'єкта інтерфейсах. На схемах інтерфейс IUnknown зображується у верхній частині об'єкта (рис. 7).
Мал. 7. Подання COM-об'єкта у вигляді схеми
У середовищі програмування Delphi в основу COM-об'єкта покладено клас TCOMObject. Його інтерфейсна частина створюється на базі опорного для будь-яких телекомунікаційних класів IInterface.
За своєю суттю інтерфейс - це договір між COM-об'єктом і клієнтським додатком, в якому COM-об'єкт гарантує клієнту надання деяких послуг. Послуги - це певні в інтерфейсі методи. Але хоча інтерфейс і має право оголошувати заголовки методів, але жоден з його методів не має опису. Це пояснюється тим, що у інтерфейсу немає розділу реалізації, він лише декларує назви методів і перелік параметрів. Клієнти можуть отримати доступ до даних COM-об'єкта тільки за допомогою покажчика на інтерфейс.
Іншим значущим аспектом інтерфейсу є те, що якщо COM-об'єкт заявляє про існування у нього певного інтерфейсу, то оголошений інтерфейс повинен обов'язково підтримуватися внутрішніми методами об'єкта і повертати будь-які значення, нехай хоча б банальне повідомлення про помилку.
Інтерфейси можуть успадковуватися - дочірній інтерфейс повинен включати всі методи свого предка. Всі існуючі інтерфейси успадковуються від базового інтерфейсу IUnknown.
Слід вказати ще на два правила, яких необхідно дотримуватися при проектуванні COM-об'єкта:
В рамках окремої системи кожен інтерфейс повинен мати унікальний ідентифікатор GUID і назву, що починається з символу «I».
4.3.1.5. Порядок виклику сервера клієнтським додатком
Мал. 8. Порядок звернення клієнта до сервера
Під час установки COM-додатки до реєстру операційної системи вноситься інформація про наявні в наявності COM-об'єктах. В першу чергу це ідентифікатор, однозначно визначає клас об'єкта (Class Identifier, CLSID). Ідентифікатори класів зберігаються в наступній гілки реєстру Windows:
Ідентифікатор CLSID - це різновид вже зустрічалися раніше глобальних унікальних ідентифікаторів (Global Unique Identifier, GUID). Це унікальне 128 бітове число, яке використовується для ідентифікації інтерфейсів, об'єктів і класів. Унікальність досягається за рахунок використання оригінального алгоритму генерації числа, що забезпечується функцією Win32 API CoCreateGuid ().
У процесі запуску COM-об'єкта безпосередню участь бере системну бібліотеку COM. На рис. 8 схематично представлена послідовність дій клієнта, бібліотеки і сервера COM при створенні першого примірника COM-об'єкта.