Сравнение управляемого и неуправляемого кода
Архитектура .NET поддерживает многочисленные языки программирования. В основном язык C++ выбирают из-за того, что в интерфейс 32-разрядных Windows-приложений (Win32 API), в программирование на основе модели компонентных объектов Microsoft (Component Object Model, COM) и в существующие программы были вложены большие средства. Таким образом, взаимодействие между управляемыми программами .NET общеязыковой среды выполнения CLR (Common Language Runtime) и неуправляемыми решениями и компонентами, написанными на C++, будет представлять интерес для многих программистов, во всяком случае, в обозримом будущем.
На сегодняшний день существуют различные формы взаимодействия, в том числе – протокол SOAP, который позволяет приложениям .NET вызывать Web-сервисы в различных платформах, в том числе в UNIX и в универсальных вычислительных машинах. Однако в этой главе мы остановимся на особом типе взаимодействия: установление связи (сопряжение; согласование) управляемого и неуправляемого кода в системе Windows. Преобладающими моделями программирования на C++ в современных системах Windows являются интерфейс 32-разрядных Windows-приложений (Win32 API) и модель компонентных объектов Microsoft (COM).
Существует большое количество действующих компонентов, основанных на модели компонентных объектов Microsoft (COM), и было бы желательно, чтобы управляемые программы .NET могли вызывать неуправляемые компоненты, построенные на основе модели компонентных объектов Microsoft (COM). Может возникнуть и обратная ситуация, когда клиенту, построенному на основе модели компонентных объектов Microsoft (COM), требуется вызвать сервер .NET.
Кроме компонентов, построенных на основе модели компонентных объектов Microsoft (COM), может возникнуть потребность в программе .NET вызвать некоторый неуправляемый код, представленный как динамически подключаемая библиотека (DLL), в том числе и интерфейс 32-разрядных Windows-приложений (Win32 API) .NET Framework поддерживает все эти сценарии взаимодействия посредством средств COM Interoperability (совместимость с моделью компонентных объектов Microsoft (COM)) и Platform Invocation Services (Службы обращения к платформе), или PInvoke.
В этой главе предполагается, что вы уже знакомы с концепциями, стоящими за существующими технологиями. Кроме того, чтобы построить предлагаемые примеры программ, вам потребуется Visual Studio 6.0, равно как и Visual Studio .NET.
Все остальные языки .NET, такие как VB.NET и С#, создают управляемый код, который может взаимодействовать с неуправляемыми библиотеками Win32 и компонентами на основе модели компонентных объектов Microsoft (COM). Однако язык VC++ .NET является единственным, который позволяет создавать как управляемый, так и неуправляемый код (не следует путать с ненадежным кодом в С#). Это дает возможность даже смешивать управляемый и неуправляемый коды в одном исходном файле. Управляемый код является кодом, динамически распределяемая память которого управляется автоматически (т.е. сборщиком мусора) общеязыковой средой выполнения CLR.
Таким образом, программист может размещать объекты в управляемой динамически распределяемой области памяти, используя оператор new (создать), причем освобождать их с помощью соответствующих операторов delete (удалить) не нужно. Это освобождает программиста от заботы об утечках памяти, и позволяет сосредоточить основное внимание на важных и полезных задачах, таких как более точная реализация проекта программы, что повышает производительность программирования и качество программного обеспечения.
Неуправляемый код C++ .NET должен самостоятельно управлять динамически распределяемой областью в памяти традиционными способами C++, используя операторы new (создать) и delete (удалить). Так как одним из наиболее общих недостатков в программах на C++ является ужасающая утечка памяти, использование управляемых расширений VC++ .NET может оказать очень положительное воздействие на многие разработки программного обеспечения. Важно отметить, что оператор delete (удалить) может явно применяться к указателю на управляемый объект, если вы хотите самостоятельно управлять освобождением памяти, занятой объектом.
Указанное обстоятельство окажется полезным в ситуациях, когда желательно выполнить деструктор объекта до того, как это сделает сам сборщик мусора, – это позволит избежать разделения. данных событий по времени в многопотоковых программах.