XPCOM часть третья: настраиваем окружение

image

 

В данной статье задействованы материалы и текст третьей части статьи про технологию XPCOM от Rick Parrish.

Прежде чем разрабатывать программное обеспечение или свои компоненты XPCOM необходимо настроить окружение.
Лучший способ проверить что все настроено и работает правильно — собрать браузер Mozilla.

Сборка дракона

Mozilla построена на основе XPCOM и XPConnect, поэтому сборка даст вам одновременно набор библиотек и полезные XPCOM компоненты. Некоторые из них вполне самостоятельные и не зависят от браузера. Посетите http://www.mozilla.org, скачайте исходный код и сопутствующие утилиты разработчика и соберите все. Код Mozilla содержит ряд общих make файлов, shell и Perl скриптов вместо специфичных файлов проекта. Это необходимо для успешной сборки проекта на различных платформах.

Такой подход потребляет много свободного места на жестком диске. Только распакованный архив с исходными кодами занимает порядка 160.975.003 байт и содержит около 28567 файлов. Из-за неэффективности NTFS потребуется порядка 244.293.632 байта свободного места. И это только исходный код! Исходный код и исполняемый файл займут порядка 450 мегабайт (не включая дополнительных утилит).

Примечание: дальнейшая часть оригинальной статьи пропущена, поскольку не актуальна на данный момент. Если вам интересно как оно было раньше — прочтите оригинал.

Настройка окружения в Ubuntu или в другой системе

Скачайте и установите следующие пакеты (необходим root):

apt-get build-dep firefox
apt-get install mercurial libasound2-dev libcurl4-openssl-dev libnotify-dev libxt-dev libiw-dev mesa-common-dev autoconf2.13 yasm

Скопируйте исходный код из центрального репозитория mozilla:

hg clone http://hg.mozilla.org/mozilla-central/

Сборка

Для сборки требуется порядка 2.5 гигабайт свободного места, и 2-4 гигабайта оперативной памяти.

Стандартная сборка (оптимизированная) не требует правки файла mozconfig, однако необходимо внести изменения в этот файл для отладочной сборки. Директория, выгруженная из репоизтория mozilla, — директория с исходными кодами (topsrcdir). Она включает множество поддиректорий, исходных файлов и make файлов. Объектные файлы и обработанные make файлы хранятся в директории objdir в процессе сборки. Mozconfig названный «.mozconfig» в корневой директории используется автоматически. Если не указать в mozconfig MOZ_OBJDIR, то будет использоваться директория @TOPSRCDIR@/obj-@CONFIG_GUESS@. Что бы указать специфичный файл mozconfig воспользуйтесь переменной окружения MOZCONFIG:

"export MOZCONFIG=/c/some/path/mozconfig"

Параллельная компиляция выполняется значительно быстрей. Рекомендуется использовать значение равное количеству ядер процессора (4 в примере ниже). Параллельная компиляция невозможна в Windows из-за бага 524149, поэтому используйте 1 (или просто удалите MOZ_MAKE_FLAGS).

Пример mozconfig для отладочной сборки:

mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/objdir-ff-debug
mk_add_options MOZ_MAKE_FLAGS="-j4"
ac_add_options --enable-debug
ac_add_options --disable-optimize

Выполните в корневой директории

make -f client.mk

для начала сборки. После успешной сборки с приведенной конфигурацией исполняемый файл firefox может быть найден в директории objdir-ff-debug/dist/bin/

Скриншот сборки firefox

Собранный firefox версии 6

Подключение XPCOM в приложении

Прежде чем приложение сможет начать использовать компоненты XPCOM необходимо загрузить и инициализировать некоторый набор библиотек.  Например, это можно сделать так:

Листинг 1. Пример приложения подключающего необходимые библиотеки

#include <stdio.h>
#include <nsIServiceManager.h>
#include <nsISomething.h>

int main()
{
   static const char szContractId[] =
      "Your component's contract ID goes here";
   nsresult rv;

   // Initialize XPCOM and check for failure ...
   rv = NS_InitXPCOM(nsnull, nsnull);
   if ( NS_FAILED(rv) )
   {
      printf("Calling NS_InitXPCOM returns [%x].n", rv);
      return -1;
   }

   // optional autoregistration - forces component manager to check for new components.
   (void)nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup, nsnull);

   // Create an instance of our component
   nsCOMPtr
 mysample = do_CreateInstance(szContractId, &rv);
   if ( NS_FAILED(rv) )
   {
      printf("Creating component instance of %s fails.n", szContractId);
      return -2;
   }

   // Do something useful with your component ...

   // (main body of code goes here)

   // Released any interfaces.

   // Shutdown XPCOM
   NS_ShutdownXPCOM(nsnull);
   return 0;
}

Обратите внимание на NS_InitXPCOM и NS_ShutdownXPCOM. Ключевые библиотеки XPCOM обычно располагаются в той же директории что и приложение, кроме того предполагается наличие поддиректории «components». После того как XPCOM инициализируется в игру вступают два больших компонента — Component Manager и Service Manager. Вызов метода AutoRegister не является обязательным, и необходим только когда устанавливаются новые компоненты.

Приведенный пример показывает самостоятельное приложение, не требующее поддержки браузера. nsISomething это заглушка вместо реального интерфейса. Вместо комментария «main body of code goes here» в настоящем приложении будет размещен код использующий этот интерфейс.

Component manager

Component manager (менеджер компонентов) занимается управлением компонентами. Он следит за тем, какие компоненты сейчас установлены, какие библиотеки необходимо загрузить для создания специфического компонента. Поддиректория «components» используется менеджером для поиска компонентов. Он просматривает директорию в момент вызова AutoRegister — ищет компоненты, которые еще не зарегистрированы  и добавляет запись во внутренний файл соответствий. Последующий запрос компонента выполняется значительно быстрее, поскольку менеджер уже знает какую библиотеку необходимо загрузить. Компоненты идентифицируются либо по 128-битному UUID (ID класса) либо по короткому имени контракта (CID — Contract ID).

Примечание для MSCOM программистов: CID это тоже самое что и Program ID или ProgID.

Рассмотрим основные методы предлагаемые менеджером компонентов через IDL. Первый ищет идентификатор класс (class ID) для заданного контракта (contract ID). Если вы хотите создать множество компонентов одного класса, но знаете только имя контракта (contract ID), то что бы повысить производительность необходимо использовать более коротки и быстрый class ID при вызове createInstance.

void contractIDToClassID(in string aContractID, out nsCID aClass);

Другой метод дает обратную функциональность:

string CLSIDToContractID(in nsCIDRef aClass, out string aClassName);

Следующий метод проверяет зарегистрирован ли и готов к использованию компонент:

boolean isRegistered(in nsCIDRef aClass);

Следующие два метода делают основную работу для загрузки XPCOM компонента. Вы выбираете как идентифицировать компонент по class ID (метод createInstance) или по contract ID (метод createInstanceByContractId). Второй параметр aDelegate необходим только тогда когда выполняется агрегация и обычно он равен nsnull. Третий параметр — идентификатор интерфейса.

voidPtr createInstance(in nsCIDRef aClass, in nsISupports aDelegate, in nsIIDRef aIID);
voidPtr createInstanceByContractID(in string aContractID, in nsISupports aDelegate, in nsIIDRef IID);

Исходный код IDL менеджера компонентов может быть найден в файле nsIComponentManager.idl.

Service manager

Как сказано в некоторых книгах сервисы XPCOM являются сингелтонами. Не важно сколько раз вы запрашиваете сервис, — вам всегда будет возвращаться интерфейс одного и того же объекта. Ранее мы уже встречались с самым большим сервисом — менеджер компонентов. Косвенно сам менеджер сервисов так же является сервисом. В двух словах, менеджер сервисов отвечает за загрузку и выгрузку сервисов. Кода происходит запрос на создание сервиса который уже загружен, менеджер сервисов возвращает ссылку на уже созданный объект сервиса вместо того что бы создать новый объект. Такое поведение отличает его от менеджера компонентов, который возвращает новый компонент на каждый запрос. Сервисы обычно запрашиваются с использованием макроса NS_WITH_SERVICE приведенного в Листинге 2.

Листинг 2. Запрос сервиса

{  // enter scope of service smart pointer ...
   NS_WITH_SERVICE(nsIMyService, service, kMyServiceCID, &rv);
   if (NS_FAILED(rv)) return rv;
   service->DoSomething(...);    // use my service
} // leaving scope of service smart pointer ...

Макрос NS_WITH_SERVICE использует nsCOMPtr для создания умного указателя. Примеры сервисов приведены в таблице 2.

Таблица 2. Примеры сервисов

  • LDAP
  • WebShell
  • JSRuntime
  • Editor
  • EventQueue
  • RDF
  • SMTP
  • IMAP
  • POP3
  • NNTP
  • DNS
  • Error
  • Logging

Category manager

Менеджер компонентов и менеджер сервисов возвращают компонент по идентификатору контракта или класса. Что вы будете делать для поиска компонентов без того и другого. В этом вам поможет менеджер категорий, он предоставляет каталог идентификаторов классов сгруппированных по категориям.

Предположим, вы пишите хороший текстовый редактор с множеством функций для обработки текстов, поддерживающий несколько типов документов через набор интерфейсов. Он поддерживает форматы: текст, HTML, RTF и PDF, так же необходимо зарегистрировать обработчик документа через категорию «document handler»  что бы программа всегда проверяла какие обработчики документов поддерживаются.

Вдруг, ваша подруга решает, что программа обязательно должна поддерживать формат WordPerfect. Она пишет новый компонент, обработчик документа, реализующий тот же набор интерфейсов и регистрирует его в соответствующей категории. Теперь любой пользователь программы может скачать, установить и начать использовать это обработчик документа без какой-либо необходимости переделывать программу с вашей стороны.

Компоненты, сгруппированные в категорию обычно имеют нечто общее, как и предопределенные наборы интерфейсов. Категория подразумевает следование некоторому контракту для любого компонента зарегистрировавшегося в ней. Категории — очень мощное средство для достижения объектной независимости, поскольку код, который использует категории должен заботиться только о соблюдении интерфейсов и может содержать любую реализацию. Несмотря на эту мощь, категории одни из самых редко используемых возможностей XPCOM.

Заключение

Вы можете говорить о себе «вооружен и очень опасен» как только достигните рубежа на котором можете собрать дерево исходных кодов Mozilla и фактически станете использовать компоненты XPCOM. Недостаток знания очень опасен, поэтому в следующих статьях мы не только научимся писать компоненты, без опасения «случайно выстрелить себе в ногу» или подстрелить чужое приложение.

Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s