Как COM обеспечивает взаимодействие языков?
Я понимаю, как COM может достичь кода C++, не зависящего от компилятора, поскольку он определяет ABI, внимательно следя за тем, какие функции языка C++ использовать. Это просто код C++, действительно умно говорящий с кодом C++. Однако я до сих пор не понимаю, как он может позволить языковое взаимодействие с C# или Javascript, например.
Где граница? Единственное объяснение, которое у меня есть сейчас, заключается в том, что сам языковой компилятор должен иметь специальную поддержку COM, чтобы он мог генерировать надлежащий код сборки, чтобы обеспечить точную связь между вызывающим / вызываемым.
3 ответа
Поскольку вы пометили свой вопрос с помощью WinRT, я предполагаю, что вы спрашиваете конкретно о том, как это достигается с помощью языковых прогнозов WinRT. В этом случае у всех языков должен быть какой-то способ сопоставить их конструкции естественного языка с COM ABI, который определяет WinRT. Этот ABI получен из метаданных, закодированных в стандарте ECMA 335, и применяются специальные правила для преобразования абстрактных метаданных в конкретный ABI. Есть естественно разные способы достичь этого. Сам CLR был обновлен для поддержки WinRT в C#. Компилятор Visual C++ был (к сожалению) дополнен языковыми расширениями для поддержки WinRT через C++/CX. Подход C++/WinRT очень отличается тем, что требует только стандартного компилятора C++, а все знания о WinRT передаются через стандартную библиотеку C++ только для заголовков. Другие языки могут использовать другие подходы, но в конце концов они должны договориться о том, как типы, выраженные в метаданных, преобразуются в объекты и вызовы виртуальных функций в ABI на основе COM.
И хотя в настоящее время этот процесс недостаточно хорошо документирован, C++/WinRT является одной из единственных проекций языка с открытым исходным кодом и, таким образом, служит полезной справочной реализацией для тех, кому необходимо понять, как WinRT работает под капотом.
https://github.com/Microsoft/xlang/tree/master/src/tool/cpp/cppwinrt
Это не волшебство, конечно.
COM устанавливает правила для языкового взаимодействия. Это просто контракт, с некоторыми полезными инструментами. Каждый язык, который хочет поддерживать COM, должен найти способ соблюдать правила самостоятельно. Все они должны предоставить свой совместимый механизм, так или иначе.
В случае C++, как вы упомянули, правила предоставляются бесплатно, но имейте в виду, что есть одно предостережение: языковой стандарт не определяет макет и механизм классов и виртуальных функций. Метод, имитируемый COM, является одной из наиболее распространенных реализаций виртуальных вызовов ("VTable"), и COM следует точной компоновке, используемой компилятором Microsoft. Но у вас может быть совершенно корректный компилятор C++, где классы с виртуальными функциями не будут совместимы с макетом COM. Просто никто этого не делает, по крайней мере, в компиляторах Windows. Так что даже в C++ есть некоторая "встреча в середине" компилятором.
В C вы должны сделать все это вручную. Другие языки могут позволить вам сделать то же самое (ассемблер, конечно).
Чтобы помочь скомпилированным языкам обмениваться информацией о конкретных контрактах, COM предоставляет библиотеки типов и механизмы для их чтения. Компилятор или язык, который хочет использовать их в своих интересах, также должен "встретиться посередине" и научиться их обрабатывать (например, Microsoft C++ #import
директива; меню библиотек VB6).
Ни один язык не будет поддерживать все, что вы можете сделать в COM, потому что есть момент (в более непонятных функциях), когда отдача от инвестиций в поддержку языка не вырастает. Каждый язык должен выбирать свои ограничения. Есть много вещей, которые вы можете сделать в COM (прочитайте спецификации IDL), что VB6 не может сделать.
Поскольку следовать правилам COM на языке, подобном сценарию, практически невозможно, COM предлагает высокоуровневый подход (автоматизация), более подходящий для динамических языков, даже если он более ограничен. Но реализатор языка, который хочет обеспечить клиентскую поддержку автоматизации, должен реализовать понимание интерфейса IDispatch, механизма активации и перевода на соответствующие средства своего языка. И язык сценариев, желающий обеспечить поддержку для создания COM-серверов, должен работать еще усерднее для реализации правильной реализации COM IDispatch и автономного хост-движка от имени пользовательских сценариев. Даже VBScript не мог сделать это в начале, пока Microsoft не добавила поддержку.SCR с Windows Scripting Host. "Встреча посередине" снова.
Если язык хочет поддерживать как чистый COM, так и Automation, ему нужно работать вдвое усерднее; поддержка одного не дает вам автоматически поддержки другого.
Для языков.NET, таких как C#, большая часть работы выполняется как для собственного COM, так и для автоматизации внутри среды выполнения.NET, которая обеспечивает реализацию COM Callable Wrappers (CCW) и Runtime Callable Wrappers (RCW), необходимых для взаимодействия с COM и устранение конфликтов между подходом подсчета ссылок в COM и подходом GC в.NET. Microsoft выполнила всю работу в одном месте, поэтому отдельным разработчикам языка.NET это не нужно.
Так что, да, разработчик языка должен работать над тем, чтобы обеспечить особую поддержку языка для COM: следуя правилам двоичного макета, реализуя слой перевода при необходимости и / или, возможно, предоставляя инструменты для чтения библиотек типов.
Языковое взаимодействие требует, чтобы обе стороны (звонящий и вызываемый) где-то "встречались посередине". COM - это просто спецификация, которая дает дизайнерам такую золотую середину, "место, где все могут встретиться".
"Библиотека типов" - это то, что обеспечивает взаимодействие компонентов COM между различными языками.
https://docs.microsoft.com/en-us/windows/desktop/midl/com-dcom-and-type-libraries
Библиотека типов (.tlb) - это двоичный файл, в котором хранится информация о свойствах и методах объектов COM или DCOM в форме, доступной для других приложений во время выполнения. Используя библиотеку типов, приложение или браузер могут определить, какие интерфейсы поддерживает объект, и вызвать методы интерфейса объекта. Это может произойти, даже если объект и клиентские приложения были написаны на разных языках программирования. Среда выполнения COM/DCOM также может использовать библиотеку типов, чтобы обеспечить автоматическое перекрестное распределение, межпроцессное и межмашинное маршалинг для интерфейсов, описанных в библиотеках типов.
Другой подход для взаимодействия языков (например, проецирование объектов C++ на Javascript) заключается в том, что COM-объект может реализовывать IDispatch.