Использование взаимодействия языка C++ (неявный PInvoke)
Обновлен: Ноябрь 2007
В отличие от других языков .NET Visual C++ поддерживает функцию взаимодействия, которая позволяет управляемому и неуправляемому коду находиться в одном приложении и даже в одном файле (вместе с директивами pragma managed, unmanaged). Это позволяет разработчикам Visual C++ интегрировать функциональность .NET в существующие приложения Visual C++, не затрагивая оставшуюся часть приложения.
Также можно вызывать неуправляемые функции из управляемой единицы компиляции с помощью dllexport, dllimport.
Неявный PInvoke полезен, если не нужно указывать способ маршалинга для параметров функции или любые другие подробности, которые можно указать при явном вызове DllImportAttribute.
Visual C++ предоставляет два способа взаимодействия управляемых и неуправляемых функций:
Явный PInvoke поддерживается платформой .NET Framework и доступен в большинстве языков .NET. Но, как и намекает его имя, взаимодействия C++ характерны для Visual C++.
Взаимодействие C++
Рекомендуется использовать взаимодействие C++, а не явный вызов PInvoke, поскольку C++ является более безопасен для типов, обычно менее трудоемок в реализации, более терпим при изменениях неуправляемого API и позволяет улучшать производительность, что представляется невозможным при явном вызове PInvoke. Однако взаимодействия в языке C++ невозможны, если неуправляемый исходный код недоступен или при компиляции с /clr:safe (дополнительные сведения см. в разделе Чистый и проверяемый код).
COM-взаимодействие в C++
Функции взаимодействия, поддерживаемые Visual C++, имеют определенное преимущество над другими языками .NET при взаимодействии с компонентами COM. Вместо нахождении в ограничениях .NET Framework Программа импорта библиотек типов (Tlbimp.exe), таких как ограниченная поддержка типов данных или обязательное предоставление каждого члена интерфейса COM, взаимодействие C++ позволяет обращаться к компонентам COM в любой момент и не требует отдельных сборок взаимодействий. Дополнительные сведения см. в разделе Использование собственных серверов COM в .NET.
Преобразуемые типы
Неуправляемые API, которые используют простые, встроенные типы (см. в разделе Преобразуемые и непреобразуемые типы), не требуют определенного кодирования, поскольку эти типы данных имеют такое же представление в памяти, но для более сложных типов данных необходим явный маршалинг. Пример см. в разделе Практическое руководство. Вызов неуправляемых библиотек DLL из управляемого кода с помощью PInvoke.
Пример
// vcmcppv2_impl_dllimp.cpp
// compile with: /clr:pure user32.lib
using namespace System::Runtime::InteropServices;
// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);
// explicit DLLImport needed here to use P/Invoke marshalling because
// System::String ^ is not the type of the first parameter to printf
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl, CharSet = CharSet::Ansi)]
// or just
// [DllImport("msvcrt.dll")]
int printf(System::String ^, ...);
int main() {
// (string literals are System::String by default)
printf("Begin beep\n");
MessageBeep(100000);
printf("Done\n");
}
Begin beep
Done
В этом разделе
Практическое руководство. Маршалинг строк ANSI с использованием взаимодействия C++
Практическое руководство. Маршалирование строк Юникода с использованием взаимодействия C++
Практическое руководство. Маршалинг строк COM посредством взаимодействия C++
Практическое руководство. Маршалирование структур с помощью взаимодействия C++
Практическое руководство. Упаковка и передача массивов с помощью взаимодействия C++
Практическое руководство. Маршалинг обратных вызовов и делегатов посредством C++ Interop
Практическое руководство. Упаковка встроенных указателей посредством взаимодействия C++
Практическое руководство. Доступ к символам объекта System::String
Практическое руководство. Преобразование строки char * в массив System::Byte
Практическое руководство. Преобразование типа System::String к wchar_t* или char*
Практическое руководство. Преобразование строки System::String в стандартную строку
Практическое руководство. Преобразование стандартной строки к типу System::String
Практическое руководство. Получение указателя на массив байтов
Практическое руководство. Загрузка неуправляемых ресурсов в массив байтов
Практическое руководство. Изменение ссылочного класса в собственной функции
Практическое руководство. Машинный код или среда CLR: определение цели созданного изображения
Практическое руководство. Добавление машинной библиотеки DLL в глобальный кэш сборок
Практическое руководство. Сохранение ссылки на тип значения в собственном типе
Практическое руководство. Хранение ссылки на объект в машинной функции
Практическое руководство. Определение факта использования ключа /clr при компиляции
Практическое руководство. Преобразование между классами System::Guid и _GUID
Практическое руководство. Использование собственного типа в компиляции /clr
Практическое руководство. Объявление дескрипторов в собственных типах
Дополнительные сведения об использовании делегатов в сценарии взаимодействий см. в разделе delegate.