2010-03-27 2 views
5

Я совершенно новый для COM, поэтому вопрос может показаться наивным.Вопросы новичка о COM

Q1. О Windows DLL

Основываясь на моем понимании, Windows DLL может экспортировать функции, типы (классы) и глобальные переменные. Это понимание в порядке?

Q2. О COM

Мое наивное понимание состоит в том, что COM-DLL - это всего лишь новый логический способ организации функций и типов, экспортируемых стандартной DLL-версией Windows. COM-библиотеки DLL экспортирует обе функции, такие как DllRegisterServer() и DllGetClassObject(), а также Классы который реализует интерфейсIUnknown. Это понимание в порядке?

Q3. * .def & * .idl

* .def используется для определения функций, экспортируемых в DLL Windows, традиционным способом, например, DllGetClassObject(). * .idl используется для определения интерфейса, реализуемого COM-классом COM.

Заранее спасибо.

ответ

14

Подумайте о COM как двоичном совместимом способе совместного использования интерфейсов через границы DLL. С ++ классы не могут быть легко экспортированы из DLL из-за нестандартного управления именами между различными версиями компилятора. COM позволяет использовать код в одной DLL или исполняемом файле, чтобы создать реализацию интерфейса из другой DLL или EXE, если эта реализация следует за определенным интерфейсом и вызовом. Это то, что позволяет COM-класс записываться на C# и вызываться из C++, Python и многих других языков, поддерживающих COM.

COM-интерфейсы являются стандартными классами C++, содержащими все чистые виртуальные функции и производными от IUnknown. IUnknown - это предопределенный интерфейс, из которого должны выполняться все совместимые COM-интерфейсы, которые предоставляют общие возможности, такие как подсчет ссылок и возможность запроса, реализует ли объект определенный интерфейс.

библиотеки DLL, которые хотят рекламировать тот факт, что они могут создавать реализации COM-интерфейсов сделать так, экспортируя 4 функцию:

  • DllGetClassObject => возвращающей фабрику классов запрошенного интерфейса
  • DllCanUnloadNow => Все ли экземпляры розданы были впоследствии освобождены
  • DllRegisterServer => Регистрация типы это DLL принадлежности в реестре
  • DllUnregisterServer => Отмена регистрации этой DLL и ее типы из реестра

Так, чтобы ответить на ваши вопросы:

Q1. О Windows DLL Исходя из моего понимания, Windows DLL может экспортировать функции, типы (классы) и глобальные переменные. Это понимание в порядке?

библиотеки DLL может экспортировать классы и функции (не уверен, о глобальных переменных, но вы не хотите, чтобы экспортировать их библиотеки DLL, даже если вы можете! :-)) Тем не менее, экспортируемые классы будут называть искажены и, следовательно, только используемые другими DLL или EXE, которые имеют одно и то же имя (не хороший способ ведения бизнеса). Функции с соглашением о вызове в стиле C не называются искаженными и, следовательно, могут быть экспортированы и вызваны из других источников без проблем.

Q2. COM DLL экспортирует обе функции, такие как DllRegisterServer() и DllGetClassObject(), , а также классы, которые реализуют интерфейс IUnknown. Это понимание всего право?

На полпути есть 4 функции для экспорта, которые должны быть полной COM-совместимой DLL (показано выше). Вы можете искать MSDN для любого из этих имен, чтобы увидеть их полную подпись. Ваша реализация для DllGetClassObject будет основной, которая будет использоваться сторонними сторонами. Они могут использовать это, чтобы получить IClassFactory для интерфейса, который предоставляет ваша DLL, а затем использовать его для создания экземпляра.

COM - большой и сложный зверь, но его фундаменты довольно просты. Вы также можете проверить эту ссылку COM Intro для получения дополнительной информации. Удачи!

+0

+1 COM не такой сумасшедший. Это позволяет вам связывать языки высокого уровня с низким уровнем разрыва. – pestilence669

4

У вас все в порядке. Единственный бит, который я бы уточнил, - это «классы, которые реализуют интерфейс IUnknown». Класс представлен объектом, реализующим интерфейс IClassFactory. Вы можете получить такую ​​фабрику классов, вызвав DllGetClassObject в DLL, а затем вы можете попросить фабрику классов сделать объект класса. Это похоже на многие другие объектно-ориентированные системы: существует множество объектов, которые представляют классы и которые могут быть использованы для производства экземпляров.

Другие полезные факты о COM:

  • Там небольшой, но сложная библиотека вспомогательных функций, в основном по имени с префиксом Co. Именно они фактически загружают библиотеки DLL, размещают экспортированные функции и вызывают их. Клиентский код обычно не вызывал бы прямой экспорт DLL (хотя довольно просто написать собственную систему хостинга для простых COM-объектов в процессе).
  • Существует важный интерфейс IDispatch, который добавляет еще один уровень абстракции, так что можно динамически идентифицировать методы для вызова объекта, используя строку для поиска метода и передачи массива значений аргументов. Это позволяет скриптовым языкам безопасно вызывать COM-объекты (т. Е. Таким образом, чтобы с ошибками программист вместо сбоев).
  • Существует более сложная система «сортировки» для разрешения вызова объектов из других потоков, других процессов или даже других компьютеров; в своем удаленном (и поддерживающем безопасность) для формы он назывался DCOM. Это не удалось ни на что похоже, как на то, что делали другие СОМ.
  • Поддержка кросс-процессов была основой OLE2, трюк, который каждое приложение бросилось на поддержку в начале 1990-х годов, большинство из которых ошибочно реализуют (очень сложные) интерфейсы и так рушится повсюду.
  • Более успешными были OLE Controls, которые были технически намного проще (не используя сортировку) и предложили способ расширить Visual Basic.
  • Существует, по крайней мере, одна широко распространенная система с поддержкой COM, которая несовместима с COM, но разделяет те же концепции (по крайней мере, простые вещи), которая называется XPCOM и является основой веб-браузера Mozilla Firefox.
  • Если вы используете COM повсеместно, у вас будет отличный способ интегрироваться с платформой .NET, поскольку он включает превосходную совместимость с COM. Но вы должны точно следовать правилам COM: AddRef/Release должен работать точно так, как определено, поэтому объект никогда не должен быть уничтожен, а его счетчик ссылок больше нуля. Должно быть возможно использовать QueryInterface, чтобы найти IUnknown с любого интерфейса и оттуда, чтобы вернуться к исходному интерфейсу, IUnknown, полученный из любого интерфейса, должен всегда иметь одинаковый адрес памяти для времени жизни объекта (поэтому его можно использовать для сравнения идентичности). Так, например: не создавайте COM-объекты в стеке и не возвращайте отдельные объекты из QueryInterface (то есть объекты, у которых есть свой собственный QueryInterface, который возвращает разные интерфейсы).
  • Основной вопрос с COM заключается в том, что он имеет как минимум два стандартных способа представления строк. Ни один из них не использует подсчет ссылок. Почему они никогда не определяли интерфейс IString вне меня, но они этого не сделали.
  • Вы сойдете с ума, если попытаетесь написать COM-код без интеллектуальных указателей для хранения ссылок или без базового класса, чтобы помочь вам реализовать интерфейсы, например. class MyClass : COM::Object<IThis, IThat> {...)
5

Чтобы добавить на хороший ответ cpalmer, есть нет особых причин, почему вы должны использовать реестр и четыре рекомендуемых функций для экспорта COM из вашей DLL.

Вы можете использовать реестр свободных COM или COM-облегченный подход, при котором вы просто экспорт фабричные методы, такие как

__declspec (dllexport) аннулируются MyDllCreateFoo (IFoo ** ppFoo);

Пользователи DLL будут звонить на ваш завод, чтобы создать свой класс CMyFoo, который реализует IFoo. Что такое DllRegisterServer et. и др. do позволяет просматривать CMyFoo и другие классы в реестре, между прочим.

Q3: Вы правы на самом деле, если не в духе. .def файлы и .idl - довольно разные звери. DEF-файлы используются только компоновщика, и даже не нужно - вы можете экспортировать все функции, которые вы хотите с помощью __declspec (dllexport) недействительными Foo() {}

внутри кода C++.

.idl файлы используются для создания заголовков C++ (.h файлов), которые включаются как DLL, так и его клиентами. Он генерирует интерфейсы плюс некоторый код клея, который выполняет такие функции, как макетирование параметров.

Опять же, вам не нужно использовать IDL для использования COM, но это может сделать вещи более удобными.

Причина, по которой я разбиваю это, состоит в том, чтобы проиллюстрировать, что COM не является большой монолитной вещью, а скорее очень маленькой вещью с кучей вещей, созданной вокруг нее, которую вы могли бы использовать, или нет , пробовать.

+0

Большое спасибо, Дрю. Да, это именно то, о чем я собираюсь напрямую экспортировать заводский метод. Потому что я просто чувствую, что просто утомительно экспортировать метод DllGetClassObject(). Я не понимал, что он уже существует и называется reg-free COM, пока не увидит ваш ответ, еще раз спасибо. – smwikipedia

+0

Извините, я могу отметить только 1 ответ в качестве ответа. – smwikipedia

Смежные вопросы