SlideShare a Scribd company logo
Сергей Балтийский
JetBrains
Why?
∞Скорость
∞ Оптимизация CPU
∞ Затраты на переключение контекста
∞Память
∞ Управление памятью
∞ GC
∞Legacy
∞ Библиотеки на C/C++
How?
∞C++/CLI
∞COM
∞PInvoke
∞Native Memory in C#
C++ CLI
∞C++ on Common Language Infrastructure
∞Наследник MC++
∞Взаимопроникающая интеграция C++ и C#
C++ CLI
∞Взаимопроникающая интеграция C++ и C#
Unmanaged classes
(classic C++)
Managed method bodies
(СIL)
Managed classes
(GC)
Unmanaged method bodies
(x86/amd64/etc)
C++ CLI — pros
∞Это интуитивно понятный выбор
∞ Язык, специально созданный для стыковки C++ и .NET
C++ CLI — pros
∞Вся мощь C++ optimizing compiler *
∞ Оптимизация на промежуточном представлении, до
выгрузки в IL (по аналогии с компиляцией в x86)
∞ Заметный результат на подходящих задачах
∞ lexing, parsing
C++ CLI — pros
∞Нетривиальные типы данных
∞ Передача между C++ и C# без маршаллинга
C++ CLI — cons
∞Проблемный компилятор
∞ Большое время компиляции
∞ Internal compiler errors
∞ Постоянные доработки и изменения
∞ Разный набор ошибок компиляции и рантайма в каждой
версии тулсета, v90 / v100 / v110 / v120
C++ CLI — cons
∞Проблемный компилятор
∞ Логические ошибки в поддержке языка
∞ пример: использование структуры,
объявленной в C# внутри generic структуры
∞ templates and generics
C++ CLI — cons
∞Проблемный оптимизатор
∞ Из-за логических проблем с каждой новой версией
компилятора отключают классы оптимизаций
∞ v120 медленнее v100
∞ Нет Profile-Guided Optimization
∞ Не работает полноценный link-time optimization
∞ Разница заметна с unity builds
C++ CLI — cons
∞Проблемное окружение
∞ Привязка к конкретной версии .NET Framework при
использовании конкретной версии компилятора
∞ v90 -> v3.5 (CLR2)
∞ v100 -> v4.0 (CLR4)
∞ v120 -> v4.5 (CLR4)
C++ CLI — cons
∞Проблемное окружение
∞ Привязка к Windows NT
∞ CoreCLR is coming
∞ Linux, MacOS на горизонте
∞ Перспективы портирования C++ CLI туманны
∞ -> /clr:pure -> /clr:safe
C++ CLI — cons
∞Проблемное окружение
∞ Разные архитектуты процессора даже внутри
Windows NT
∞ Файл содержит native code и не является AnyCPU
∞ Множественная компиляция под разные CPU
∞ Плохо сочетается с C# внутри одного SLN
C++ CLI — cons
∞Проблемное окружение
∞ CRT dynamic linking only
∞ Невозможно получить самодостаточный статически
слинкованный файл
∞ CRT Redist
∞ Для некоторых версий — только через SxS (v90)
∞ Не поместить 32/64 в один каталог
C++ CLI — cons
∞Неведомое и непознанное
∞ При загрузке в secondary appdomain происходит
утечка исполнения в primary appdomain
∞ Пример сценария: nUnit unit tests загружает рабочий код в
специальный аппдомен
∞ В primary appdomain могут быть недоступны assembly
references
∞ Может отсутствовать appbase / private bin path / binding
redirects / assembly resolver, который помогает находить
файлы в родном appdomain
∞ -> невозможность работы в таком сценарии
C++ CLI — cons
∞Неведомое и непознанное:
appdomain leak workarounds
∞ Не использовать статические переменные с managed
handles
∞ Не использовать CRT (после v90)
∞ И что угодно ещё в новых версиях компилятора
C++ CLI — cons
∞Провоцирует писать код
в managed режиме в духе C++
C++ CLI
COM
∞Component Object Model
∞Набор конвенций для вызовов между
рантаймами разной природы (“ABI”)
∞ Функции
∞ Структуры данных
∞ Объекты
∞ Время жизни объектов
∞ Exceptions
COM
∞First-class support in .NET
∞ .NET — идеологический потомок COM/COM+/DCOM
∞ Windows Runtime — альтернативная ветвь развития
∞ .NET CLR не основан на COM внутри
∞ Но в нём встроена фундаментальная поддержка COM
∞ .NET ← COM
∞ COM ← .NET
COM — pros
∞Выглядит почти как managed object
∞Легко импортируется в C#
∞Интегрируется в GC
∞Managed/native код живёт отдельно
∞Можно линковать статически
COM — cons
∞Другая threading model
∞Спецприём для создания самого первого объекта
для xcopy deployment
∞Утечки памяти при неосторожном обращении
∞Portability*
process
COM within .NET: appdomains
appdomain appdomain
COM
process
COM within .NET: runtimes
CLR 2 CLR 4
COM
process
COM within .NET: processes
CLR CLR
COM
process
COM within .NET: Interprocess Call
Ole32Dll::CreateItemMoniker(null, name)
Ole32Dll::GetRunningObjectTable(0)
rot.Register
(
ROTFLAGS_REGISTRATIONKEEPSALIVE,
instance,
moniker
)
rot.GetObject(moniker)
publish get
IDispatch vs Reflection
∞Late-bound calls по имени функции
∞.NET ← COM
∞ Если есть IDispatch
∞ Reflection, dynamic keyword
∞COM ← .NET
∞ ComInterfaceType: InterfaceIsIDispatch,
InterfaceIsDual
COM in .NET
∞RCW: Runtime Callable Wrapper
∞ Автоматическое преобразование в COM-вызовах
∞ Вручную через Marshal::GetObjectForIUnknown
COM Object Lifetime
∞Reference counting: AddRef, Release
∞ +1 при создании объекта
∞ При достижении 0 объект сам себя уничтожает
∞Правила обращения со счётчиком ссылок
∞ При получении в in-параметре: не трогать
∞ При записи в field: +1, потом не забыть -1
∞ При отдаче в out-параметр: +1
∞ При получении из out-параметра
COM AddRef/Release in C++
∞При получении в in-параметре: ничего не трогать
HRESULT DoWork(IUnknown *pUnk)
{
// просто используем pUnk внутри функции
}
COM AddRef/Release in C++
∞При длительном хранении: +1, -1
HRESULT DoWork(IUnknown *pUnk)
{
// запись в member variable
pUnk->AddRef();
m_pUnk = pUnk;
// не забыть сделать Release() в деструкторе
// или при стирании
}
COM AddRef/Release in C++
∞При возврате (out-параметр, return): +1
(-1 должен сделать получатель)
HRESULT DoWork(IUnknown **ppUnk)
{
// отдаём свой объект
*ppUnk = m_pUnk;
m_pUnk->AddRef();
}
COM AddRef/Release in C++
∞При получении возвращаемого значения: -1
IUnknown *pUnk = NULL;
DoWork(&pUnk);
// тут пользуемся pUnk
pUnk->Release();
Reference Counting & GC
∞RCW держит одну ссылку на COM Object
∞ Одна на все интерфейсы одного объекта
∞ Делает AddRef при первом знакомстве
∞ Делает Release в своём finalizer (или вручную)
Reference Counting & GC
∞У RCW есть ещё один reference counter
∞ Отражает количество попаданий COM объекта в CLR
∞ Уменьшается при Marshal::ReleaseComObject
∞ При достижении 0 отпускает COM объект
∞ и становится недоступным для использования из дотнета
Marshal::ReleaseComObject
∞Позволяет вовремя отпустить COM объект
∞ Можно этим не заниматься
∞ Тогда объект отпустится когда-нибудь, по GC
∞Для этого и нужен второй reference counter
∞ Отражает представление пользователя о том, сколько
раз объект был независимо получен из внешнего
мира
∞Опасно вызвать слишком много раз
∞ “COM object that has been separated from its
underlying RCW cannot be used.”
Reference Counting & GC
∞GC не боится циклов
∞Но если цикл проходит через COM,
то опять боится
.NET in COM
∞CCW: COM Callable Wrapper
∞ Автоматическое преобразование в COM-вызовах
∞ Автоматически при создании .NET-COM-объекта из
нативного кода
∞ Вручную через Marshal::GetIUnknownForObject
.NET in COM
∞Атрибуты на managed типах
∞ ComVisibleAttribute
∞ GuidAttribute
∞ ComInterfaceTypeAttribute
Reference Counting & GC
∞CCW не даст GC собрать объект
∞ Это вам не delegate в PInvoke
.NET → COM → .NET
∞Из цепочки RCW-CCW извлекается настоящий
.NET объект
Importing Declarations
∞COM → .NET
∞ .TLB → .DLL/C#
∞ TLBIMP.EXE
∞ “Add COM Reference” in Visual Studio
∞ Написание интерфейса вручную по MIDL/MSDN/.h
∞ dynamic / Reflection
∞.NET → COM
∞ .DLL → .TLB (→ #import )
∞ TLBEXP.EXE
∞ Case collisions
∞ нельзя иметь COM-visible типы, отличающиеся только регистром
Primary Interop Assembly
∞ Эталонный авторский TLBIMP
∞ С native COM objects можно иметь несколько
альтернативных деклараций одновременно
∞ Совместимость интерфейсов только по GUID
∞ Совместимость функций только по порядковому номеру
∞ Managed COM objects требуют PIA
∞ Цепочки RCW-CCW сворачиваются, виден настоящий CLR
объект
∞ Совместимость интерфейсов/методов по правилам CLR
∞ Послабления в CLR4 (for Visual Studio)
COM & Exceptions
∞Error codes вместо exceptions
∞HRESULT (32-bit integer)
∞ 0 → OK
∞ <0 → Error
∞ >0 → Success with details
∞IErrorInfo
∞.NET умеет преобразовывать
HRESULT ↔ exception
∞ optionally
∞ С потерей success code
PreserveSig
∞ MIDL:
∞ HRESULT GetObject
(
[in, unique] IMoniker *pmkObjectName,
[out] IUnknown **ppunkObject
);
∞ C# PreserveSig
∞ [MethodImpl(MethodImplOptions.PreserveSig)]
Int32 GetObject(IMoniker pmkObjectName,
[MarshalAs(UnmanagedType.Interface)] out object ppunkObject);
∞ C# non-preserve-sig
∞ [return:MarshalAs(UnmanagedType.Interface)] object
GetObject(IMoniker pmkObjectName)
∞ Можно не проверять вручную, была ли ошибка
∞ Невозможно отличить S_OK от S_FALSE
.NET Threading
∞ApartmentState::STA
∞ApartmentState::MTA
COM Apartments
∞ Условное понятие
∞ Группа объектов, которые могут вызывать друг друга
напрямую
∞ Группа тредов, в которой объекты вызывают друг
друга напрямую
∞ COM Thread принадлежит одному Apartment
∞ COM Object принадлежит одному Apartment
∞ Функции объекта будут вызываться только с его тредов*
Single-Threaded Apartment
∞Single thread
∞Cooperative multitasking
∞Windows message pump
∞ Обязательно прокачивать сообщения на таком треде
∞ Вызовы из других тредов приходят как windows
messages
∞ Синхронно либо асинхронно
∞Reentrancy
Multi-Threaded Apartment
∞Максимум один в процессе
∞Содержит все MTA-треды
∞Использует thread pool для входящих вызовов
Threads & Apartments
∞STA
∞STA0
∞MTA
∞n/a
COM Object Threading Models
∞n/a
∞Single
∞Apartment
∞Both
∞Free
∞(Free-Threaded Marshaller)
∞ (+ neutral)
∞ Влияет на создание объекта системными средствами
Creating a COM Object
STA0 STA MTA
n/a • → STA0 → STA0
Single • → STA0 → STA0
Apartment • • → STA
Both • • •
Free → MTA → MTA •
COM Object Pointer & Apartments
∞ISomeInterface*
∞В пределах одного apartment можно
использовать напрямую
∞При передаче в другой apartment:
∞ ISomeInterface* → byte stream →
другой ISomeInterface*
∞ Новый указатель будет неявно исполнять код в
другом треде (если надо)
∞.NET делает это сам внутри RCW
RCW & Apartments
∞Неявный блокирующий вызов в домашний
apartment
∞STA
∞ Домашний STA объекта должен быть доступен
∞ Message pump
∞ Особенно при финализации RCW
COM Registration
∞Classic: Windows Registry
∞ Per-machine or per-user
∞ Не дружит с XCOPY
∞SxS
∞ “Registration-Free COM Interop” @MSDN
∞Classic WinAPI
∞ __declspec(dllexport) extern “c” функция
∞Ручной вызов стандартных функций
∞ DllGetClassObject
THE END

More Related Content

PPTX
Когда в C# не хватает C++ . Часть 2.
PDF
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
PDF
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
PPTX
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
PPTX
Григорий Демченко, Асинхронность и неблокирующая синхронизация
PPTX
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
PPTX
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
PDF
Модель памяти C++ - Андрей Янковский, Яндекс
Когда в C# не хватает C++ . Часть 2.
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Модель памяти C++ - Андрей Янковский, Яндекс

What's hot (20)

PDF
C++ exceptions
PPTX
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
ODP
Как за час сделать недельную работу
PDF
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...
PDF
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
PDF
Максим Хижинский Lock-free maps
PDF
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
PDF
JIT-компиляция в виртуальной машине Java (HighLoad++ 2013)
PPTX
Аскетичная разработка браузера
PDF
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
PDF
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
PDF
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
PDF
Intel IPP Samples for Windows - работа над ошибками
PDF
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
PDF
Павел Довгалюк, Обратная отладка
PPTX
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
PDF
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
PPTX
Опыт разработки статического анализатора кода
PDF
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
PPTX
разработка серверов и серверных приложений лекция №3
C++ exceptions
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как за час сделать недельную работу
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
Максим Хижинский Lock-free maps
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
JIT-компиляция в виртуальной машине Java (HighLoad++ 2013)
Аскетичная разработка браузера
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
Intel IPP Samples for Windows - работа над ошибками
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
Павел Довгалюк, Обратная отладка
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Опыт разработки статического анализатора кода
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
разработка серверов и серверных приложений лекция №3
Ad

Similar to Когда в C# не хватает C++ (20)

PPTX
Когда в C# не хватает C++ . Часть 3.
PPTX
Управление памятью в CPython
PDF
Алексей Андросов - Debugger: Отладка кода
PPTX
Принципы работы статического анализатора кода PVS-Studio
PPTX
SECON'2016. Чубарь Алексей, Мобильные грабли Unity
PPTX
Парсим и кодогенерируем для С++ с использованием clang
PPTX
New Android NDK & JNI
PDF
Разница в подходах анализа кода компилятором и выделенным инструментом
PDF
20130429 dynamic c_c++_program_analysis-alexey_samsonov
PDF
Акторы на C++: стоило ли оно того?
PPTX
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PDF
Построение компилятора на базе LLVM — Павел Сычев
PDF
2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется все
PDF
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
PPTX
Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...
PDF
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
PPTX
Performance optimization effective interaction with virtual machine
PDF
2016-12-03 02 Алексей Городецкий. Как пишут компиляторы
PPTX
NetworkUA - 2012 - Introduction TypeScript
PDF
доклад про Llvm
Когда в C# не хватает C++ . Часть 3.
Управление памятью в CPython
Алексей Андросов - Debugger: Отладка кода
Принципы работы статического анализатора кода PVS-Studio
SECON'2016. Чубарь Алексей, Мобильные грабли Unity
Парсим и кодогенерируем для С++ с использованием clang
New Android NDK & JNI
Разница в подходах анализа кода компилятором и выделенным инструментом
20130429 dynamic c_c++_program_analysis-alexey_samsonov
Акторы на C++: стоило ли оно того?
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
Построение компилятора на базе LLVM — Павел Сычев
2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется все
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Чем заняться вечером, если я знаю сколько будет ++i + ++i / Андрей Бородин (Y...
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Performance optimization effective interaction with virtual machine
2016-12-03 02 Алексей Городецкий. Как пишут компиляторы
NetworkUA - 2012 - Introduction TypeScript
доклад про Llvm
Ad

More from Mikhail Shcherbakov (20)

PPTX
Delegates and events in C#
PPTX
Mythbusters - Web Application Security
PPTX
Михаил Щербаков "WinDbg сотоварищи"
PPTX
Apache Ignite.NET в действии
PPTX
Архитектура Apache Ignite .NET
PPTX
Знакомство с In-Memory Data Grid
PDF
сценарии использования статического анализатора
PPTX
WCF. Легко или проблемно
PDF
Поиск ошибок в программах на языке C#
PDF
Project Rider
PPTX
WinDbg в руках .NET разработчика
PPTX
Structured logging
PPTX
RESTful API: Best practices, versioning, design documentation
PPTX
Простой и кросс-платформенный WEB-сервер на .NET
PPTX
Использование Visual Studio Tools for Apache Cordova в реальных проектах
PPTX
Sandboxing in .NET CLR
PDF
Распространённые ошибки оценки производительности .NET-приложений
PDF
Как это работает: DLR
PPTX
Visual Studio 2015 Diagnostic and Debugging Tools
PDF
Разработка мобильных приложений на С# с использованием Xamarin
Delegates and events in C#
Mythbusters - Web Application Security
Михаил Щербаков "WinDbg сотоварищи"
Apache Ignite.NET в действии
Архитектура Apache Ignite .NET
Знакомство с In-Memory Data Grid
сценарии использования статического анализатора
WCF. Легко или проблемно
Поиск ошибок в программах на языке C#
Project Rider
WinDbg в руках .NET разработчика
Structured logging
RESTful API: Best practices, versioning, design documentation
Простой и кросс-платформенный WEB-сервер на .NET
Использование Visual Studio Tools for Apache Cordova в реальных проектах
Sandboxing in .NET CLR
Распространённые ошибки оценки производительности .NET-приложений
Как это работает: DLR
Visual Studio 2015 Diagnostic and Debugging Tools
Разработка мобильных приложений на С# с использованием Xamarin

Когда в C# не хватает C++

  • 2. Why? ∞Скорость ∞ Оптимизация CPU ∞ Затраты на переключение контекста ∞Память ∞ Управление памятью ∞ GC ∞Legacy ∞ Библиотеки на C/C++
  • 4. C++ CLI ∞C++ on Common Language Infrastructure ∞Наследник MC++ ∞Взаимопроникающая интеграция C++ и C#
  • 5. C++ CLI ∞Взаимопроникающая интеграция C++ и C# Unmanaged classes (classic C++) Managed method bodies (СIL) Managed classes (GC) Unmanaged method bodies (x86/amd64/etc)
  • 6. C++ CLI — pros ∞Это интуитивно понятный выбор ∞ Язык, специально созданный для стыковки C++ и .NET
  • 7. C++ CLI — pros ∞Вся мощь C++ optimizing compiler * ∞ Оптимизация на промежуточном представлении, до выгрузки в IL (по аналогии с компиляцией в x86) ∞ Заметный результат на подходящих задачах ∞ lexing, parsing
  • 8. C++ CLI — pros ∞Нетривиальные типы данных ∞ Передача между C++ и C# без маршаллинга
  • 9. C++ CLI — cons ∞Проблемный компилятор ∞ Большое время компиляции ∞ Internal compiler errors ∞ Постоянные доработки и изменения ∞ Разный набор ошибок компиляции и рантайма в каждой версии тулсета, v90 / v100 / v110 / v120
  • 10. C++ CLI — cons ∞Проблемный компилятор ∞ Логические ошибки в поддержке языка ∞ пример: использование структуры, объявленной в C# внутри generic структуры ∞ templates and generics
  • 11. C++ CLI — cons ∞Проблемный оптимизатор ∞ Из-за логических проблем с каждой новой версией компилятора отключают классы оптимизаций ∞ v120 медленнее v100 ∞ Нет Profile-Guided Optimization ∞ Не работает полноценный link-time optimization ∞ Разница заметна с unity builds
  • 12. C++ CLI — cons ∞Проблемное окружение ∞ Привязка к конкретной версии .NET Framework при использовании конкретной версии компилятора ∞ v90 -> v3.5 (CLR2) ∞ v100 -> v4.0 (CLR4) ∞ v120 -> v4.5 (CLR4)
  • 13. C++ CLI — cons ∞Проблемное окружение ∞ Привязка к Windows NT ∞ CoreCLR is coming ∞ Linux, MacOS на горизонте ∞ Перспективы портирования C++ CLI туманны ∞ -> /clr:pure -> /clr:safe
  • 14. C++ CLI — cons ∞Проблемное окружение ∞ Разные архитектуты процессора даже внутри Windows NT ∞ Файл содержит native code и не является AnyCPU ∞ Множественная компиляция под разные CPU ∞ Плохо сочетается с C# внутри одного SLN
  • 15. C++ CLI — cons ∞Проблемное окружение ∞ CRT dynamic linking only ∞ Невозможно получить самодостаточный статически слинкованный файл ∞ CRT Redist ∞ Для некоторых версий — только через SxS (v90) ∞ Не поместить 32/64 в один каталог
  • 16. C++ CLI — cons ∞Неведомое и непознанное ∞ При загрузке в secondary appdomain происходит утечка исполнения в primary appdomain ∞ Пример сценария: nUnit unit tests загружает рабочий код в специальный аппдомен ∞ В primary appdomain могут быть недоступны assembly references ∞ Может отсутствовать appbase / private bin path / binding redirects / assembly resolver, который помогает находить файлы в родном appdomain ∞ -> невозможность работы в таком сценарии
  • 17. C++ CLI — cons ∞Неведомое и непознанное: appdomain leak workarounds ∞ Не использовать статические переменные с managed handles ∞ Не использовать CRT (после v90) ∞ И что угодно ещё в новых версиях компилятора
  • 18. C++ CLI — cons ∞Провоцирует писать код в managed режиме в духе C++
  • 20. COM ∞Component Object Model ∞Набор конвенций для вызовов между рантаймами разной природы (“ABI”) ∞ Функции ∞ Структуры данных ∞ Объекты ∞ Время жизни объектов ∞ Exceptions
  • 21. COM ∞First-class support in .NET ∞ .NET — идеологический потомок COM/COM+/DCOM ∞ Windows Runtime — альтернативная ветвь развития ∞ .NET CLR не основан на COM внутри ∞ Но в нём встроена фундаментальная поддержка COM ∞ .NET ← COM ∞ COM ← .NET
  • 22. COM — pros ∞Выглядит почти как managed object ∞Легко импортируется в C# ∞Интегрируется в GC ∞Managed/native код живёт отдельно ∞Можно линковать статически
  • 23. COM — cons ∞Другая threading model ∞Спецприём для создания самого первого объекта для xcopy deployment ∞Утечки памяти при неосторожном обращении ∞Portability*
  • 24. process COM within .NET: appdomains appdomain appdomain COM
  • 25. process COM within .NET: runtimes CLR 2 CLR 4 COM
  • 26. process COM within .NET: processes CLR CLR COM process
  • 27. COM within .NET: Interprocess Call Ole32Dll::CreateItemMoniker(null, name) Ole32Dll::GetRunningObjectTable(0) rot.Register ( ROTFLAGS_REGISTRATIONKEEPSALIVE, instance, moniker ) rot.GetObject(moniker) publish get
  • 28. IDispatch vs Reflection ∞Late-bound calls по имени функции ∞.NET ← COM ∞ Если есть IDispatch ∞ Reflection, dynamic keyword ∞COM ← .NET ∞ ComInterfaceType: InterfaceIsIDispatch, InterfaceIsDual
  • 29. COM in .NET ∞RCW: Runtime Callable Wrapper ∞ Автоматическое преобразование в COM-вызовах ∞ Вручную через Marshal::GetObjectForIUnknown
  • 30. COM Object Lifetime ∞Reference counting: AddRef, Release ∞ +1 при создании объекта ∞ При достижении 0 объект сам себя уничтожает ∞Правила обращения со счётчиком ссылок ∞ При получении в in-параметре: не трогать ∞ При записи в field: +1, потом не забыть -1 ∞ При отдаче в out-параметр: +1 ∞ При получении из out-параметра
  • 31. COM AddRef/Release in C++ ∞При получении в in-параметре: ничего не трогать HRESULT DoWork(IUnknown *pUnk) { // просто используем pUnk внутри функции }
  • 32. COM AddRef/Release in C++ ∞При длительном хранении: +1, -1 HRESULT DoWork(IUnknown *pUnk) { // запись в member variable pUnk->AddRef(); m_pUnk = pUnk; // не забыть сделать Release() в деструкторе // или при стирании }
  • 33. COM AddRef/Release in C++ ∞При возврате (out-параметр, return): +1 (-1 должен сделать получатель) HRESULT DoWork(IUnknown **ppUnk) { // отдаём свой объект *ppUnk = m_pUnk; m_pUnk->AddRef(); }
  • 34. COM AddRef/Release in C++ ∞При получении возвращаемого значения: -1 IUnknown *pUnk = NULL; DoWork(&pUnk); // тут пользуемся pUnk pUnk->Release();
  • 35. Reference Counting & GC ∞RCW держит одну ссылку на COM Object ∞ Одна на все интерфейсы одного объекта ∞ Делает AddRef при первом знакомстве ∞ Делает Release в своём finalizer (или вручную)
  • 36. Reference Counting & GC ∞У RCW есть ещё один reference counter ∞ Отражает количество попаданий COM объекта в CLR ∞ Уменьшается при Marshal::ReleaseComObject ∞ При достижении 0 отпускает COM объект ∞ и становится недоступным для использования из дотнета
  • 37. Marshal::ReleaseComObject ∞Позволяет вовремя отпустить COM объект ∞ Можно этим не заниматься ∞ Тогда объект отпустится когда-нибудь, по GC ∞Для этого и нужен второй reference counter ∞ Отражает представление пользователя о том, сколько раз объект был независимо получен из внешнего мира ∞Опасно вызвать слишком много раз ∞ “COM object that has been separated from its underlying RCW cannot be used.”
  • 38. Reference Counting & GC ∞GC не боится циклов ∞Но если цикл проходит через COM, то опять боится
  • 39. .NET in COM ∞CCW: COM Callable Wrapper ∞ Автоматическое преобразование в COM-вызовах ∞ Автоматически при создании .NET-COM-объекта из нативного кода ∞ Вручную через Marshal::GetIUnknownForObject
  • 40. .NET in COM ∞Атрибуты на managed типах ∞ ComVisibleAttribute ∞ GuidAttribute ∞ ComInterfaceTypeAttribute
  • 41. Reference Counting & GC ∞CCW не даст GC собрать объект ∞ Это вам не delegate в PInvoke
  • 42. .NET → COM → .NET ∞Из цепочки RCW-CCW извлекается настоящий .NET объект
  • 43. Importing Declarations ∞COM → .NET ∞ .TLB → .DLL/C# ∞ TLBIMP.EXE ∞ “Add COM Reference” in Visual Studio ∞ Написание интерфейса вручную по MIDL/MSDN/.h ∞ dynamic / Reflection ∞.NET → COM ∞ .DLL → .TLB (→ #import ) ∞ TLBEXP.EXE ∞ Case collisions ∞ нельзя иметь COM-visible типы, отличающиеся только регистром
  • 44. Primary Interop Assembly ∞ Эталонный авторский TLBIMP ∞ С native COM objects можно иметь несколько альтернативных деклараций одновременно ∞ Совместимость интерфейсов только по GUID ∞ Совместимость функций только по порядковому номеру ∞ Managed COM objects требуют PIA ∞ Цепочки RCW-CCW сворачиваются, виден настоящий CLR объект ∞ Совместимость интерфейсов/методов по правилам CLR ∞ Послабления в CLR4 (for Visual Studio)
  • 45. COM & Exceptions ∞Error codes вместо exceptions ∞HRESULT (32-bit integer) ∞ 0 → OK ∞ <0 → Error ∞ >0 → Success with details ∞IErrorInfo ∞.NET умеет преобразовывать HRESULT ↔ exception ∞ optionally ∞ С потерей success code
  • 46. PreserveSig ∞ MIDL: ∞ HRESULT GetObject ( [in, unique] IMoniker *pmkObjectName, [out] IUnknown **ppunkObject ); ∞ C# PreserveSig ∞ [MethodImpl(MethodImplOptions.PreserveSig)] Int32 GetObject(IMoniker pmkObjectName, [MarshalAs(UnmanagedType.Interface)] out object ppunkObject); ∞ C# non-preserve-sig ∞ [return:MarshalAs(UnmanagedType.Interface)] object GetObject(IMoniker pmkObjectName) ∞ Можно не проверять вручную, была ли ошибка ∞ Невозможно отличить S_OK от S_FALSE
  • 48. COM Apartments ∞ Условное понятие ∞ Группа объектов, которые могут вызывать друг друга напрямую ∞ Группа тредов, в которой объекты вызывают друг друга напрямую ∞ COM Thread принадлежит одному Apartment ∞ COM Object принадлежит одному Apartment ∞ Функции объекта будут вызываться только с его тредов*
  • 49. Single-Threaded Apartment ∞Single thread ∞Cooperative multitasking ∞Windows message pump ∞ Обязательно прокачивать сообщения на таком треде ∞ Вызовы из других тредов приходят как windows messages ∞ Синхронно либо асинхронно ∞Reentrancy
  • 50. Multi-Threaded Apartment ∞Максимум один в процессе ∞Содержит все MTA-треды ∞Использует thread pool для входящих вызовов
  • 52. COM Object Threading Models ∞n/a ∞Single ∞Apartment ∞Both ∞Free ∞(Free-Threaded Marshaller) ∞ (+ neutral) ∞ Влияет на создание объекта системными средствами
  • 53. Creating a COM Object STA0 STA MTA n/a • → STA0 → STA0 Single • → STA0 → STA0 Apartment • • → STA Both • • • Free → MTA → MTA •
  • 54. COM Object Pointer & Apartments ∞ISomeInterface* ∞В пределах одного apartment можно использовать напрямую ∞При передаче в другой apartment: ∞ ISomeInterface* → byte stream → другой ISomeInterface* ∞ Новый указатель будет неявно исполнять код в другом треде (если надо) ∞.NET делает это сам внутри RCW
  • 55. RCW & Apartments ∞Неявный блокирующий вызов в домашний apartment ∞STA ∞ Домашний STA объекта должен быть доступен ∞ Message pump ∞ Особенно при финализации RCW
  • 56. COM Registration ∞Classic: Windows Registry ∞ Per-machine or per-user ∞ Не дружит с XCOPY ∞SxS ∞ “Registration-Free COM Interop” @MSDN ∞Classic WinAPI ∞ __declspec(dllexport) extern “c” функция ∞Ручной вызов стандартных функций ∞ DllGetClassObject

Editor's Notes

  • #8: Roslyn cheats on generated functions for dlls
  • #14: GCC CLI
  • #15: Fusion can’t load multiple files
  • #19: Обёртки-обёртки-обёртки Много аллокаций якобы на стеке
  • #20: Обёртки-обёртки-обёртки Много аллокаций якобы на стеке
  • #21: Application binary interface the calling convention sizes, layout, and alignment of data types
  • #22: “COM+ 2” .net is NOT based on COM on the inside Windows Runtime as a sibling to COM
  • #25: Analogous to MarshalByRefObject Can’t say it’s fully managed here
  • #26: Analogous to MarshalByRefObject
  • #27: Analogous to MarshalByRefObject
  • #48: pumping