Поделиться через


Использование взаимодействия языка 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

В этом разделе

Сведения об использовании делегатов в сценарии взаимодействия см. в разделе "Делегаты" (расширения компонентов C++).

См. также