Использование взаимодействия языка C++ (неявный PInvoke)
В отличие от других языков .NET, Visual C++ поддерживает взаимодействие, которое позволяет существовать управляемый и неуправляемый код в одном приложении и даже в том же файле (с управляемыми, неуправляемыми прагмами). Это позволяет разработчикам Visual C++ интегрировать функции .NET в существующие приложения Visual C++ без нарушения остальной части приложения.
Вы также можете вызывать неуправляемые функции из управляемого компилятора с помощью dllexport, dllimport.
Неявный PInvoke полезен, если не нужно указывать способ маршалирования параметров функции или любые другие сведения, которые можно указать при явном вызове DllImportAttribute.
Visual C++ предоставляет два способа взаимодействия управляемых и неуправляемых функций:
Явный PInvoke поддерживается платформа .NET Framework и доступен на большинстве языков .NET. Но, как подразумевает его имя, взаимодействие C++ зависит от Visual C++.
взаимодействие C++
Взаимодействие C++ обеспечивает более высокую безопасность типов, и, как правило, менее емким для реализации. Однако взаимодействие C++ не является вариантом, если неуправляемый исходный код недоступен или для кроссплатформенных проектов.
COM-взаимодействие в C++
Функции взаимодействия, поддерживаемые Visual C++, предоставляют определенное преимущество по сравнению с другими языками .NET, когда речь идет о взаимодействии с com-компонентами. Вместо ограничения платформа .NET Framework Tlbimp.exe (импорт библиотеки типов), таких как ограниченная поддержка типов данных и обязательное воздействие каждого члена каждого интерфейса COM, взаимодействие C++ позволяет com-компонентам обращаться к ним и не требует отдельных сборок взаимодействия. В отличие от Visual Basic и C#, Visual C++ может использовать COM-объекты непосредственно с помощью обычных механизмов COM (таких как CoCreateInstance и QueryInterface). Это возможно из-за функций взаимодействия C++, которые вызывают автоматическую вставку кода перехода из управляемого в неуправляемые функции и обратно.
С помощью взаимодействия C++ компоненты COM можно использовать в обычном режиме или их можно упаковать в классы C++. Эти классы-оболочки называются настраиваемыми вызываемыми оболочками среды выполнения или CRCW, и они имеют два преимущества по сравнению с использованием COM непосредственно в коде приложения:
Полученный класс можно использовать на языках, отличных от Visual C++.
Сведения о com-интерфейсе можно скрыть из управляемого клиентского кода. Типы данных .NET можно использовать вместо собственных типов, а сведения о маршале данных можно выполнять прозрачно внутри CRCW.
Независимо от того, используется ли COM напрямую или через CRCW, типы аргументов, отличные от простых, blittable типов должны быть маршалированы.
Типы blittable
Для неуправляемых API, использующих простые встроенные типы (см . Blittable и не blittable Types), не требуется специальное кодирование, так как эти типы данных имеют одинаковое представление в памяти, но более сложные типы данных требуют явного маршалинга данных. Пример см. в статье "Практическое руководство. Вызов собственных БИБЛИОТЕК 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++
Практическое руководство. Маршалинг встроенных указателей посредством взаимодействия C++
Практическое руководство. Доступ к символам объекта System::String
Практическое руководство. Преобразование строки char * в массив System::Byte
Практическое руководство. Преобразование типа System::String к wchar_t* или char*
Практическое руководство. Преобразование строки System::String в стандартную строку
Практическое руководство. Преобразование стандартной строки к типу System::String
Практическое руководство. Получение указателя на массив байтов
Практическое руководство. Загрузка неуправляемых ресурсов в массив байтов
Практическое руководство. Изменение ссылочного класса в собственной функции
Практическое руководство. Машинный код или среда CLR: определение цели созданного образа
Практическое руководство. Добавление машинной библиотеки DLL в глобальный кэш сборок
Практическое руководство. Сохранение ссылки на тип значения в собственном типе
Практическое руководство. Хранение ссылки на объект в неуправляемой памяти
Практическое руководство. Преобразование между классами System::Guid и _GUID
Практическое руководство. Использование собственного типа в компиляции /clr
Практическое руководство. Объявление дескрипторов в собственных типах
Практическое руководство. Создание программы-оболочки собственного класса для использования в C#
Сведения об использовании делегатов в сценарии взаимодействия см. в разделе "Делегаты" (расширения компонентов C++).