Как скомпилировать idl файл

Обновлено: 05.07.2024

Microsoft Interface Definition Language (MIDL) определяет интерфейсы между клиентскими и серверными программами. Microsoft включает компилятор MIDL в комплект средств Software Development Kit (SDK), что позволяет разработчикам создавать файлы языка описания интерфейсов (IDL) и файлы конфигурации приложения (ACF), необходимые для удаленного вызова процедур (RPC) интерфейсов и COM/DCOM интерфейсов.

Содержание

Области применения

MIDL может быть использован во всех клиент-серверных приложениях, написанных для операционных систем семейства Windows. Он также может применяться для создания клиентских и серверных программ для гетерогенных сетевых сред, включающих такие операционные системы, как Unix и Apple. Для взаимодействия Microsoft поддерживает стандарт Open Group (ранее известный как Фонд открытого программного обеспечения) DCE RPC.

Необходимые навыки для использования MIDL

При использовании MIDL с RPC, требуется знакомство с языком программирования C/C++ и знание RPC парадигмы. При использовании MIDL с COM (англ. Component Object Model — объектная модель компонентов), необходимо понимание как C++ и RPC применяются в COM, или, в качестве альтернативы, требуется опыт работы с OLE Automation моделью сценариев и типом библиотек.

Интерфейс в распределённых объектах

В распределенных вычислительных системах, интерфейс представляет собой набор определений и удаленных функций, который позволяет двум и более программам взаимодействовать различными способами. В приложении RPC, интерфейс определяет:* Как клиентские и серверные приложения идентифицируют себя.

  • Как данные передаются между клиентом и сервером.
  • Удаленные процедуры, которые могут обратиться к клиентскому приложению.
  • Типы данных для параметров и возвращаемых значений удаленных процедур.

Microsoft Interface Definition Language (MIDL) служит для реализации интерфейсов, используемых в распределенных приложениях. С MIDL, приложение может иметь один или несколько интерфейсов. Каждый интерфейс определяет уникальный распределенный протокол между программами клиента и сервера. Приложения, основанные на удаленных вызовов процедур (RPC), Component Object Model (COM), и Distributed Component Object Model (DCOM) указывают свои интерфейсы, используя MIDL.

Interface Definition (IDL) File

Файл, который содержит в себе интерфейс и определения библиотек, называется файлом IDL, и имеет IDL-расширение. На практике, компилятор MIDL будет разбирать файл описания интерфейса, независимо от его расширения. Интерфейс идентифицируется набором ключевых слов. Каждый интерфейс состоит из заголовка и тела. Заголовок содержит атрибуты, которые применяются ко всему интерфейсу. Тело содержит оставшиеся определения интерфейса.

Пример IDL файла

Example.idl

В примере файла IDL определяется два COM интерфейса. Из этого IDL файла, утилита Midl.exe будет генерировать прокси/заглушки, файлы заголовков и проводить маршалинг кода.

Директива IDL import используется, чтобы подключить файл заголовка, Mydefs.h, который содержит пользовательские типы, и Unknwn.idl, содержащий определение IUnknown, от которого наследуются IFace1 и IFace2.

Атрибут object идентифицирует интерфейс в качестве объекта интерфейса и сообщает компилятору о необходимости сгенерировать код MIDL прокси/заглушек вместо RPC на клиенте и серверных заглушек. Методы интерфейса должны возвращать тип HRESULT, чтобы позволить основному механизму RPC сообщить об ошибках при вызове методов, которые не получилось завершить из-за проблем с сетью.

Использование uuid атрибута определяет идентификатор интерфейса (IID). Каждый интерфейс, класс и тип библиотеки должны быть идентифицированы собственным уникальным идентификатором. Для генерации набора с уникальными идентификаторами для интерфейсов и других компонентов используется утилита Uuidgen.exe.

Ключевое слово interface определяет имя интерфейса. Все объекты должны быть производными, прямо или косвенно, от IUnknown.

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

Атрибут pointer_default определяет тип указателя по умолчанию (unique, ref, or ptr) для всех указателей кроме тех, что включенны в списки параметров. Если тип по умолчанию не задан, MIDL предполагает, что отдельные указатели являются unique. Тем не менее, если у вас есть несколько уровней указателей, вы должны явно указать тип указателя по умолчанию, даже если вы хотите, чтобы тип был unique.

В предыдущем примере, массив BkfstStuff[] является динамически расширяемым массивом, размер которого определяется во время выполнения программы. Атрибут max_is определяет переменную, содержащую максимальное значение индекса массива.

Атрибут size_is также используется, чтобы указать размер массива, или, как в предыдущем примере, несколько уровней указателей. В примере, вызов может быть сделан, несмотря на то, что заранее может быть не известно, сколько данных будет возвращено.

Example2.idl

Следующий пример IDL (который повторно использует интерфейсы, описанные в предыдущем примере IDL) показывает различные способы получения типов информационных библиотек для интерфейсов.

Атрибут helpstring является обязательным; вы используете его для краткого описания объекта или предоставления строки состояния. Это помогает строкам быть читаемым из объекта браузера, например, из того, который предоставляет Microsoft Visual Basic.

Атрибут dual на IFace3 создает интерфейс, который является одновременно интерфейсом доставки и интерфейсом COM Поскольку он является производным от IDispatch. Двойной интерфейс поддерживает автоматизацию, что определяет атрибут oleautomation. IFace3 импортирует oaidl.idl, чтобы получить определение IDispatch.

Оператор library определяет библиотеку типов ExampleLib, которая имеет свои собственные атрибуты uuid, helpstring, и version.

В определении типа библиотека, директива importlib импортирует составленный тип библиотеки. Все определения типа библиотека должны быть внесены в библиотеку базового типа, определенную в Stdole32.tlb.

Предложенное определение типа библиотека демонстрирует три различных пути включения интерфейсов. IFace3 подключается лишь путем обращения его к объявлению библиотеки.

Оператор coclass определяет совершенно новый класс компонента, BkfstComponent, который включает в себя два ранее определенных интерфейса, IFace1 и IFace2. Атрибут default определяет IFace1 как интерфейс по умолчанию.

IFace4 описывается в операторе library. Атрибут propput на MethodD показывает, что метод выполняет определенное действие со свойством с тем же именем. Атрибут propget указывает, что метод извлекает информацию из свойства с тем же именем, что и метод. Атрибут retval в MethodD обозначает выходной параметр, который содержит возвращаемое значение функции.

Компиляция MIDL

Используя IDL файл, например Example2.idl, который определяет один или несколько COM интерфейсов и типов библиотек, компилятор MIDL (Midl.exe) генерирует файлы, описанные в следующей таблице в качестве вывода по умолчанию.

Имя файла Описание
Example2.h Файл заголовка, содержащий определения типа и объявления функций для всех интерфейсов, определенных в файле IDL, а также опережающее объявление для подпрограмм, вызывающих заглушки.
Example2_p.c Прокси/заглушка файл, который включает в себя суррогатные точки входа и для клиентов, и для серверов.
Example2_i.c Файл идентификатор интерфейса, который определяет идентификатор GUID для каждого интерфейса, указанного в файле IDL.
Example2.tlb Файл, который содержит информацию о типах и объектах.
Dlldata.c Содержит данные, необходимые для создания DLL прокси/заглушки.

Параметры компиляции MIDL

Вы можете использовать следующие параметры командной строки, чтобы переопределить некоторые значения по умолчанию компилятора MIDL и выбрать оптимизацию подходящую для вашего приложения.

Параметр Описание
/acf Используется для явной подачи ACF файла. Этот переключатель также позволяет использовать различные имена интерфейсов в файлах IDL и ACF.
/dlldata Определяет имя файла для генерируемого файла данных DLL для DLL прокси. Имя файла по умолчанию Dlldata.c.
/env Указывает MIDL генерировать заглушки или тип библиотека для целевой среды.
/header, /h Задает имя файла заголовка интерфейса. По умолчанию именем является то, что лежит в IDL файле с расширением .h.
/iid Определяет файл идентификатор интерфейса, который перекрывает файл идентификатор интерфейса по умолчанию в интерфейсе для COM.
/lcid Обеспечивает полную поддержку DBCS, так что вы можете использовать международные символы в свои входных файлах, именах файлов и путей к каталогам.
/no_format_opt По умолчанию, чтобы уменьшить размер кода, MIDL устраняет дубликаты дескрипторов. Этот переключатель отключает эту возможность оптимизации.
/Oi, /Oic, /Oif Указывает MIDL использовать полностью интерпретированный метод маршалинга. /Oic и /Oicf коммутаторы обеспечивают дополнительные улучшения производительности.
/out Определяет каталог, в который компилятор MIDL запишет выходные файлы. Каталог вывода может быть указан буквой имени диска, абсолютным именем пути, или и тем и другим. По умолчанию, MIDL выводит файлы в текущий каталог.
/proxy Определяет имя прокси-файла интерфейса для интерфейса COM. По умолчанию используется имя файла IDL плюс "_p.c".
/tlb Определяет имя файла типа библиотека. По умолчанию используется имя файла IDL, с .tlb расширением.

Загрузка и регистрация типа библиотека

Автоматическая динамическая ссылочная библиотека, Oleaut32.dll, предоставляет несколько функций, которые можно вызывать для загрузки и регистрации файлов типа библиотека. Вызов LoadTypeLibEx, как показано в следующем примере, и загружает библиотеку, и создает записи в реестре.

Пример

Сборка и регистрация прокси DLL

Если вы выбрали прокси/заглушка для маршалинга вашего приложения, то .c и .h файлы, которые MIDL сгенерирует должны быть скомпилированы и слинкованы так, чтобы создать прокси DLL, и DLL должен быть отражён в системном реестре, чтобы клиенты могли найти свои интерфейсы. MIDL-сгенерированный файл Dlldata.c содержит необходимые процедуры и другую информацию для создания и регистрации прокси/заглушка DLL.

Первым шагом в построении DLL является написание файла определения модуля для линкера, как показано в следующем примере:

В качестве альтернативы, вы можете указать эти экспортируемые функции в LINK в командной строке вашего Makefile.

Экспортируемые функции, объявленные в Rpcproxy.h, которая включает в себя Dlldata.c и реализацию по умолчанию, являются частью библиотеки RPC run-time. COM использует эти функции, чтобы создать фабрику классов, разгрузить библиотеки DLL (убедившись, что не существует ни одного объекта или lock элемента), получить информацию о прокси-DLL и самостоятельно зарегистрироваться и отменить регистрацию DLL-прокси. Чтобы воспользоваться этими функциями, вы должны ссылаться на Cpreprocessor / D (или -D) опция, когда вы компилируете файлы Dlldata.c и Example_p.c, как показано в следующем Makefile:

Если вы не укажете эти определения препроцессора во время компиляции, эти функции не определятся автоматически. (То есть, макросы в Rpcproxy.c ничего не расширят) Тогда вы должны определить их явно в другом исходном файле, модуль которого будет также включен в окончательную линковку и компиляцию в командной строке компилятора C.

Когда определяется REGISTER_PROXY_DLL, Rpcproxy.h обеспечивает дополнительное условное управление компиляции с PROXY_CLSID = GUID, PROXY_CLSID_IS = явное значение GUID, и ENTRY_PREFIX = префикс строки.

Ручная регистрация прокси DLL

Если по какой-то причине вы не можете использовать прокси-процедуры по умолчанию для регистрации заглушек, вы можете вручную зарегистрировать библиотеку DLL, добавив следующие записи в системный реестр, используя Regedt32.exe.

На этом шаге мы рассмотрим строение IDL- файла .

  • исходный текст представителя/заглушки для стандартного маршалинга;
  • файл библиотеки типов;
  • С -файл с определениями GUID компонента и интерфейсов;
  • заголовочный файл C/C++ с объявлениями методов интерфейсов, предоставляемых компонентом.

Созданный мастерами исходный текст представителя/заглушки для объекта Encoder содержится в файлах DllData.c и EncodeServer_p.c . В результате их компиляции создается DLL представителя/заглушки, используемая СОМ для маршалинга данных через границы процессов. Файл библиотеки типов EncodeServer.tlb подключается к DLL в момент сборки компонента.

Позже мы научимся использовать эти файлы в клиентских программах.

Вот как выглядит файл EncodeServer.idl :

В этом IDL -файле определен СОМ -объект (сокласс) Encoder , интерфейс IEncoder и библиотека типов ENCODESERVERLib . Как видно из этого примера, синтаксис IDL очень похож на C++ , а самое сильное различие - это заключенные в квадратные скобки атрибуты перед объявлением каждого объекта.

MIDL -атрибуты определяют характеристики интерфейсов, соклассов и библиотек. Например, [uuid] - обязательный атрибут, определяющий уникальный идентификатор (GUID) для каждого из этих объектов. Все идентификаторы GUID в этом файле сгенерированы мастерами ATL . Обратите внимание на атрибуты [propput] и [propget] - они информируют языки типа Visual Basic , что с методом нужно обращаться, как со свойством.

Заметьте, что определение сокласса находится в определении библиотеки типов. Это означает, что описание СОМ -объекта будет включено в библиотеку типов. Объявляя сокласс вне библиотечного блока, Вам удастся избежать включения информации о СОМ -объекте в библиотеку типов. Это весьма полезно при создании СОМ -объектов, используемых только внутренним образом, например лишь другими объектами этой же DLL .

На следующем шаге мы рассмотрим альтернативные способы создания COM- объектов .

пакет SDK для Windows Media диспетчер устройств содержит как файлы заголовков, так и исходные IDL-файлы для большинства этих файлов заголовков. Файлы заголовков находятся в \ папке Inc \ в пути установки пакета SDK. IDL-файлы находятся в \ \ папке IDL.

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

Эквивалентный IDL и предоставленные файлы заголовков

IDL Эквивалентный указанный заголовок Описание
ВМДМ. idl
ВМСП. idl
ВМСКП. idl
икомпонентаусентикате. idl
Мсвмдм. h Все четыре файла IDL включены в этот один указанный заголовок.
Вмдм. idl определяет все интерфейсы приложения, а также необходимые структуры, константы и коды ошибок.
Вмсп. idl определяет все интерфейсы поставщика услуг.
Вмскп. idl определяет все интерфейсы, значения GUID и константы, необходимые для защиты поставщиков содержимого.
икомпонентаусентикате. idl определяет интерфейс икомпонентаусентикате .
Вмдмлог. idl Вмдмлог. h
вмдмлог _ i. c
Определяет интерфейсы ведения журнала.
Необходимо использовать оба этих файла заголовков, а не только h-файл, из-за проблемы с файлом IDL.
Вмдрмдевицеапп. idl Вмдрмдевицеапп. h Определяет интерфейсы ивмдрмдевицеапп и IWMDRMDeviceApp2 , используемые приложениями для обновления управления цифровыми правами на устройствах или счетчиков воспроизведения на устройствах.

Зависимости IDL

Некоторые из предоставленных IDL-файлов имеют зависимости сборки. Если вы планируете компилировать IDL-файлы самостоятельно, необходимо обработать эти внешние зависимости в порядке, показанном в следующей таблице.

Реализация распределенной системы - это нетривиальная задача. Для реализации распределенной системы с использованием Java и CORBA необходимы следующие шаги:

  1. выполнить анализ и проектирование на основе моделирования предметной области, моделирования системы и декомпозиции системы на ряд подсистем;
  2. создать IDL -описание путем спецификации API распределенных подсистем и спецификации структур данных, которые передаются через границы системы;
  3. реализовать сервант, используя файлы, сгенерированные IDL -компилятором;
  4. реализовать клиент, используя файлы заглушек, сгенерированные IDL -компилятором;
  5. принять решение о методе распространения объектных ссылок сервантов (обычно это делается с помощью сервиса именования, но не обязательно);
  6. запустить реализацию серванта;
  7. запустить клиент.

После определения подсистем нужно решить, каким из них придать форму распределенных сервисов. Если предположить, что структура всех подсистем реализует функциональность распределенных совместно используемых сервисов, то перевод таких подсистем на платформу CORBA существенно упрощается. В любом случае, открытый API такого сервиса будет доступен клиентам. Для объектно-ориентированного подхода обычно интерфейс, описываемый в IDL , может являться некоторым подмножеством всех реализуемых сервером функций. И даже после реализации сервера (мы используем Java в качестве языка программирования) разработчиков продолжает волновать вопрос о том, сколько дополнительных функций (административных, связанных с защитой и т.д.) предоставить серверу.

Если существуют структуры данных, которые сервер должен возвращать клиенту (или принимать от него), то описание и определение этих структур данных должно присутствовать в IDL -файле. Модель CORBA предоставляет возможность процедурным языкам программирования описывать конструкции в "псевдообъектном" стиле. Две конструкции CORBA поддерживают этот механизм: struct и valuetype . Клиент и сервер передают IDL -структуры ( struct ) туда и обратно в качестве обычных данных. Стандартная оптимизация включает в себя отправку этих данных непосредственно клиенту, чтобы освободить сервер от избыточных запросов. Конструкция valuetype является IDL -описанием некоторой сущности, включающей и данные, и методы. Конструкция struct состоит только из данных (конструкция struct , скомпилированная в Java -код, определяет открытые атрибуты), тогда как valuetype инкапсулирует данные, и добавляет логику, необходимую для создания объекта, простого или сложного, какой требуется.

После объявления API сервера в виде IDL -файла единственное, чего не достает, - это собственно реализация сервера. Компилятор IDL анализирует IDL -файл и генерирует соответствующие файлы на целевом языке. После того как созданы вспомогательные файлы, разработчик может писать код реализации; до этого момента единственное, что было сделано разработчиком, - это объявлены интерфейс, атрибуты и данные, необходимые серверу для обработки запросов. Сначала разработчик может реализовать фиктивный сервер, который просто возвращает текстовые данные, чтобы другой разработчик мог написать клиент (или, возможно, текстовый клиент) для тестирования обращений к серверу. Более типичный пример - сервер, который является оболочкой унаследованного приложения, но скрывает это от клиентов.

Первый пример

Данный пример реализует решение задачи про сеть столовых, использующую в своей работе с клиентами пластиковые карты.

Интерфейс сервера BillingService включает четыре метода: addNewCard (добавляет новую карту), addMoney (добавляет денежные средства на карту), subMoney (снимает денежные средства с карты), getCardBalance (показывает текущий баланс карты).

Файл BillingService.idl

В примере 6.1 приведено IDL -описание сервера BillingService.

CORBA не является предписанием реализации, поэтому IDL -описание формально программным кодом не является. Ключевое слово module связывает данное имя непосредственно с пакетом Java . Вложенные имена module , соединенные вместе, дают полное имя пакета . Имя module в примере 6.1 - BillingServiceModule.

Фигурные скобки в строках 4 и 13 обозначают границы области действия блока. В IDL точка с запятой всегда завершает блок (включая объявление module ). Java , C , C++ являются языками с блочной структурой и используют похожий синтаксис, но в них блок не рассматривается как строка, требующая для завершения точки с запятой. Отсутствие точки с запятой в IDL является синтаксической ошибкой.

Строки 5-12 являются объявлением интерфейса сервера BillingService . Указанный сервер представляет собой производный класс (конкретную реализацию) интерфейса BillingService . Отсутствие привязки к клиенту является сознательным, допускается произвольная реализация сервера.

Следующим шагом в реализации нашего приложения будет генерация из IDL -определения вспомогательных классов. В самом деле, то, что написано в IDL -файле, очень напоминает определение интерфейса java или абстрактного класса C++ . Вполне естественно, что созданы инструменты, автоматически генерирующие соответствующие конструкции на базовом языке. Кроме того, мы говорили о том, что базовые типы IDL должны транслироваться в соответствующие типы целевой системы программирования . И опять же, такого рода трансляция может осуществляться автоматически, соответствующим образом сгенерированным кодом.

Компиляция файла idl

Компиляция файла BillingService.idl компилятором Java-IDL idlj,входящим в состав пакета jdk фирмы Sun , осуществляется так:

Позднее мы рассмотрим утилиту Java idlj и ее параметры командной строки . По умолчанию утилита idlj для каждого определенного в idl модуля создает пакет java , а для элементов модуля создает набор java -классов, включенных в этот пакет.

Разработка opendds java (2): генерация кода в соответствии с IDL

содержание

IDL является аббревиатурой языка описания интерфейса, относится к языку описания интерфейса, являетсяCORBAЧасть спецификации,Перекрестная платформаОснование развития.

Вот мессенджер .IDL в примере Messenger в качестве примера:

Он состоит из трех частей:

  • Модуль: внешний слой, вы можете понять имя проекта для создания
  • Назначение Pragma: укажите тип данных и ключ, передаваемый в проекте OpenDDS, каждый тип данных может иметь ноль для нескольких клавиш, функция ключа - определить разные экземпляры
  • Структура: Директива Pragma Указанные Тип данных

1) Тип целочисленного числа: короткие (2 байта), длинные длинные длинные (8 байт), а их без знаки

2) Плавающая точка: поплавок (4 байта), двойные (8 байт), длинные двойные (16 байт)

3) Характер: char, wchar, string, wstring

4) Boolean: Boolean

5) octa-type: октет

Типы структуры включают структуру, интерфейс, объединение и т. Д.

Обычно используется строка, двойной, длинный, логический.

Официальный документ Глава 10 Описание - создать проекты SLN, написав файлы MPC, и я не делаю это непосредственно на код C ++ и Java. Сначала необходимо создать код C ++ в соответствии с шагами в главе 2, а затем генерировать код Java в соответствии с шагом 10.

Компилятор C ++ необходимо использовать при компиляции, и если это среда Windows, вы можете работать в командной строке разработчика Visual Studio. Сначала используйте Tao_idl.exe, чтобы скомпилировать файл IDL, который вы просто пишете:

Generate: USERMANAGERC.CPP, USERMANAGERC.H, USERMANAGERC.INL, USERMANAGERS.CPP, пять файлов

Затем используйте OpenDDS_IDL для компиляции:

На данный момент: USERMANAGERTYPESUPPORT.IDL, USERMANAGERTYPESUPPORTIMPL.CPP, USERMANAGERTYPESUPPORTIMPL.h Три файла

Скомпилируйте вновь сгенерированный USERMANAGERTYPESUPPORT.IDL для компиляции Tao_idl

Во-первых, нажмите Главу 10, генерируйте USERMANAGER_EXPORT.H (это имя может быть небрежно, пока могут быть последовательны следующие файлы MPC):

Затем напишите файл MPC для генерации проекта, вы можете скопировать Messenger_IDL_TEST.MPC под% opengds_home% \ Java \ Tests \ Messenger \ Messenger_idl:

Файл SLN должен быть сгенерирован в это время. Если происходит следующее исключение, рассмотрите возможность компиляции с использованием MPC.PL, что генерирует файл vcxproj:

Обратите внимание, что значение вышеперечисленного выше варианта необходимо определить в соответствии с фактической ситуацией, и использование VS 2019, которые я использую, может открыть и компилировать проект VS 2017.

Далее откройте проект, пригласим настроить Windows SDK, напрямую подтвердите, если компьютер 64 является системой, вам необходимо изменить X86 рядом с «Debug» на X64, затем выполнить «генерацию» - «Создание решения» может Отказ

Во время процесса генерации может быть предложено пропустить JNI_MD.h, который копируется в каталог% OpenDDS_HOME% \ Java \ Idl2jni \ Runtime в% java_home% \ включает в себя каталог \ win32.

В этот момент вы можете получить USERMANAGER.jar и usermanagerd.dll (потому что он генерируется в режиме отладки, если это режим выпуска, если режим выпуска генерируется, если это режим выпуска, если это режим выпуска, Оставшийся файл можно удалить.

Первый - удалить зависимость от Messenger_idl_test.jar и добавить USERMANAGER.jar. В это время три файла Java определенно будут сообщать о неправильном красном, и они будут изменены в этих местах.

Затем измените -djava.library.path в варианте VM к:

Читайте также: