Как стать автором
Обновить

Комментарии 38

Начало положено!

Изобретаем D-Bus? Так он давно уже изобретён.

Он совместим с MS COM? Если нет, то есть D-Bus, как правильно сказали, если да, то рекомендую еще посмотреть в исходники wine и reactos.

D-bus не слишком жирно, для внутрипроцессного взаимодействия?
Вместо того, чтобы виртуальные функции дёргать...

Это вы системный webview не использовали, который подтикает на windows. Лучше все в отдельных процессах.

Отдельные процессы — само по себе довольно жирно для многих задач :)

При большем объёме соместимого кода с Windows, жить будет веселее, и ошибок в Windows будут находить больше некоторое ПО, которое живёт только на Windows из-за COM/DCOM, спокойно легче может быть портировано на Linux.


Например, можно будет редактировать в Microsoft Excel for Windows, не вставая со стула имея все возможности Linux

Для критиков "зачем это на Linux": COM — это универсальное ABI для кросс-языкового объектно-ориентированного взаимодействия. На текущий момент встроенные средства Linux и OSX такое ABI определяют только для обычных функций в стиле C.


Мы успешно применяем COM для взаимодействия кода на C# с объектно-ориентированным кодом на C++. За счёт встроенного рефкаунтинга время жизни объектов прозрачно регулируется, ABI даёт переносимость между платформами.


Шарповую обёртку генерим средствами SharpGenTools.


В частности посредством COM сделан новый бэкэнд под OSX для AvaloniaUI, других вменяемых способов сделать слой интеграции с ObjC просто нет. А тут clang-овский ARC обеспечивает интеграцию рефкаунтинга C++ и ObjC, а COM обеспечивает интеграцию C++ и C#.


Соорудил базовый заголовок с описанием IUnknown, реализацию ComPtr и ComObject и поехали. Дальше определяем набор интерфейсов и можно прозрачно их использовать из кода на C# как родные.

Так Xamarin.Mac же...

Гвоздями приколочен к патченому моно, в которое добавили костыли для GC. Не работает ни на неткоре, ни на стоковом моно.

настолько универсальное, что нормально работать с ним можно лишь в студии, в которой для COM-объектов есть несколько расширений компилятора

Ну вот у меня проблем с реализацией на связке clang/XCode не возникло

Из того, с чем сталкивался я при попытке скрестить c# утилиту с mingw:
1. midl из комплекта VS умеет генерировать либо COM-интерфейс для студии (со студийными расширениями), либо не обернутый для остальных компиляторов. Во втором режиме не поддерживает часть функционала, midl выдаст ошибку при его наличии в idl файле. Решение: править idl руками
2. сгенерированный заголовочник не компилится в mingw из-за очередного использования нестандартных расширений msvc типа forward enum declaration (нетипизированного). Решение: править руками
3. т.к. в «универсальном» варианте полностью отсутствует всяческая обвязка, необходимо самому дописывать всю обработку ошибок COM. «Родной» вариант прокидывает их в виде исключений.

В итоге то, что делается прагмой #import в студии, вне студии выливается в несколько дней курения документации плюс несколько дней написания оберток.
  1. Используем SharpGenTools, на вход подаём сразу плюсовые заголовки, всё работает.
  2. Не используем midl, см. выше
  3. Все обёртки нагенерил SharpGenTools.

Пример рабочего проекта см. по ссылкам выше.

но мне нужно было дергать c# из плюсов, а не наоборот

Тогда проблем выше вообще в принципе нет. Тем же самым SharpGenTools генерите по заголовкам трамплины (в терминологии — Shadow), которые нативному коду выдают нормальный C++-совместимый vtable. С точки зрения плюсового кода это выглядит как обычный указатель на интерфейс.

НЛО прилетело и опубликовало эту надпись здесь
Так сложно было читать статью с таким большим количеством грамматических ошибок…
Ничего себе. В 2018-ом то. У меня сложилось впечатление, что COM и DCOM и на windows уже скорее мертв, чем жив; а вы его на Linux.

Базовая часть COM — это по сути обычные интерфейсы из C++. Просто в корне иерархии наследования оных должен быть IUnknown с реализацией счётчика ссылок и каста к другим интерфейсам. На этом собственно всё.

Ну а как же стабильный ABI?
Сделать все функции в обязательном порядке __cdecl или __stdcall (правда тут переменное число аргументов никак не получится, так что для vararg только __cdecl) и полностью запретить __fastcall, вот и получится стабильный ABI.
Вообще-то это чисто сишная технология, отсюда и универсальный ABI. Ее более удобно обернули в C++. Что естественно.
string scope = cmdline(«scope», "");

Ну, наверное, для примеров достаточно, а так — стоило бы убедиться, откуда и куда мы будем пытаться работать.
COM — довольно дурная технология. Её проблема — в «корпоративной» стабильности. Один объект, неверно подсчитывающий свои ссылки — и всё, приплыли. В лучшем случае — утечка памяти, в худшем — ссылки на уже удаленный объект.

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

Не стоит выкапывать эту стюардессу без нужды. Лучше сделать что-то аналогичное на умных указателях.

Одно исключение — это OPC (прежде всего OPC DA). Оно завязано на DCOM. Но при реализации — нарветесь на проблемы с «корпоративной» стабильностью.

С такой аргументацией нельзя использовать вообще никакие гномовские библиотеки. Они же все на GLib, а там g_object_ref и g_object_unref.

Почему? Подсчет ссылок можно сделать по-разному. Можно иметь автоматические средства проверки. Можно иметь хорошие правила. Можно иметь макрос и темплейты, автоматизирующие подсчет.

В COM- ничего этого нет. Типичная ситуцаия в COM. Есть объект А, у него интрефейс IA. Через этот интерфейс получаем интерфейсы IB и IC. Они могут относится к объекту А, а могут — ко вложенным объектам B и С. Это зависит от реализации. В результате, уничтожая ссылку на IA, мы можем получить неработоспобность B и С, потому что А им нужен, а он уничтожился (точнее при уничтожении А уничтожает B и С). А можем — не получить. И все это зависит от конкретной реализации, которая бывает какая угодно.

Описываемая вами ситуация произойти не может, т. к. QueryInterface увеличивает счётчик ссылок возвращаемого объекта.

Да ну? Обоснуйте. Каким образом, увеличение ссылок для возвращаемого интерфейса IB может помещать мне сделать release для IA?
Давайте я ещё раз медленно и печально проясню ситуацию. Есть объект A с интерфейсом IA. Внутри него находится объект B c интерфейсом IB. Объект B написан независимо и ничего про объект А не знает. При удалении объекта А, он удаляет и объект B, причем не взирая на его счетчик ссылок.

Получаем IA, от него получаем IB, делаем release на IA, Память, занята объектом B, возвращается в кучу. Через 15 минут использования интерфейса IB (объекта B) он зависает.

Причем вы можете проверять своего клиента на десятке серверов. Все будет отлично работать, ибо у них интерфейсы IA и IB относятся к одному объекту А (или сделано делегирование вместо агрегатирования). А потом нарветесь на сервер с такой схемой — и кранты. Причем замены этому серверу нет, для данного устойства он один.

Это вот и есть чудный мир OPC и COM.
При удалении объекта А, он удаляет и объект B, причем не взирая на его счетчик ссылок.

Это прямое нарушение принципов работы с COM. Все COM-объекты должны быть в куче и все ссылки на COM-объект должны быть через умные указатели либо соответствующие механизмы клиентского языка. Описываемая вами явная ошибка программиста в коде компонента может случиться при использовании любой системы работы с учётом ссылок.

Увы, в учебниках по COM встречается и агрегирование и делегирование. И это не «ошибка», а довольно распространенная практика реализации. Вплоть до примеров из книг от microsift press.

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

Агрегирование и делегирование подразумевают раздельный подсчёт ссылок. Удаление объекта с живыми ссылками — это всегда явный косяк того, кто писал реализацию и к COM как таковому отношения не имеет.

Вот вы уже и запутались. Excel — это большой объект. Но внутри него сидит куча других объектов. Запускаем Excel руками, потом подключаемся к его вложенным объектам по COM/DCOM. Затем закрываем. Что будет при раздельном подсчете ссылок? Excel закроется и похоронит все вложенные объекты.

Вся фишка в том, что объемлющий объект должен иметь общий подсчет ссылок со вложенными. А не раздельный. Но, поскольку вложенные объекты могут быть независимыми (inProc COM изDLL ), это не всегда возможно.

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


На тему "досрочного" протухания дочерних объектов хорошо написано здесь

Да любая библиотека, которую вы можете подключить к своей программе, может дать вам утечки памяти, краши и т.д. Это общая проблема использования чужого кода. Совершенно непонятно, при чем тут COM?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации