Вопросы о новичке о COM

Я довольно плохо знаком с COM, таким образом, вопрос может казаться наивным.

Q1. О Windows DLL

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

Q2. О COM

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

Q3. *.def и *.idl

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

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

6
задан smwikipedia 5 April 2010 в 03:10
поделиться

3 ответа

Думайте о COM как о двоичном совместимом способе совместного использования интерфейсов через границы DLL. Классы C ++ не могут быть легко экспортированы из 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 для получения дополнительной информации. Удачи!

14
ответ дан 8 December 2019 в 05:20
поделиться

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

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

__ declspec (dllexport) void MyDllCreateFoo (IFoo ** ppFoo);

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

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

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

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

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

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

5
ответ дан 8 December 2019 в 05:20
поделиться

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

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

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

Похожие вопросы: