Korzystanie z międzyoperacyjności języka C++ (niejawna funkcja PInvoke)
W przeciwieństwie do innych języków platformy .NET język Visual C++ obsługuje współdziałanie, które umożliwia istnienie zarządzanego i niezarządzanego kodu w tej samej aplikacji, a nawet w tym samym pliku (z zarządzanymi, niezarządzanymi pragmasami). Dzięki temu deweloperzy języka Visual C++ mogą integrować funkcje platformy .NET z istniejącymi aplikacjami Visual C++ bez zakłócania pozostałej części aplikacji.
Funkcje niezarządzane można również wywoływać z zarządzanego compilandu przy użyciu dllexport, dllimport.
Niejawna funkcja PInvoke jest przydatna, gdy nie trzeba określać sposobu marshalingu parametrów funkcji lub innych szczegółów, które można określić podczas jawnego wywoływania atrybutu DllImportAttribute.
Visual C++ udostępnia dwa sposoby współdziałania funkcji zarządzanych i niezarządzanych:
Jawne wywołanie PInvoke jest obsługiwane przez program .NET Framework i jest dostępne w większości języków platformy .NET. Jednak jak sama nazwa wskazuje, międzyoperacyjności języka C++ jest specyficzne dla języka Visual C++.
międzyoperacyjność C++
Interop języka C++ zapewnia lepsze bezpieczeństwo typów i zwykle jest mniej żmudny do zaimplementowania. Jednak międzyoperacyjności języka C++ nie jest opcją, jeśli niezarządzany kod źródłowy nie jest dostępny lub w przypadku projektów międzyplatformowych.
współdziałanie języka C++ z modelem COM
Funkcje współdziałania obsługiwane przez program Visual C++ oferują szczególną przewagę nad innymi językami platformy .NET, jeśli chodzi o współdziałanie ze składnikami COM. Zamiast ograniczać się do ograniczeń programu .NET Framework Tlbimp.exe (importer biblioteki typów), takich jak ograniczona obsługa typów danych i obowiązkowe ujawnienie każdego elementu członkowskiego każdego interfejsu COM, międzyoperacyjność języka C++ umożliwia dostęp do składników COM w dowolnym momencie i nie wymaga oddzielnych zestawów międzyoperacyjnych. W przeciwieństwie do języka Visual Basic i C#, visual C++ może używać obiektów COM bezpośrednio przy użyciu zwykłych mechanizmów COM (takich jak CoCreateInstance i QueryInterface). Jest to możliwe ze względu na funkcje międzyoperacyjności języka C++, które powodują, że kompilator automatycznie wstawia kod przejścia, aby przejść z zarządzanych do niezarządzanych funkcji i z powrotem.
Korzystając z międzyoperacyjności języka C++, składniki COM mogą być używane w zwykły sposób lub mogą być opakowane wewnątrz klas języka C++. Te klasy otoki są nazywane niestandardowymi otokami wywołującymi środowisko uruchomieniowe lub CRCW i mają dwie zalety korzystania z modelu COM bezpośrednio w kodzie aplikacji:
Wynikowa klasa może być używana z języków innych niż Visual C++.
Szczegóły interfejsu COM mogą być ukryte w zarządzanym kodzie klienta. Typy danych platformy .NET mogą być używane zamiast typów natywnych, a szczegóły marshalingu danych można wykonywać w sposób niewidoczny w CRCW.
Niezależnie od tego, czy com jest używany bezpośrednio, czy za pośrednictwem CRCW, typy argumentów inne niż proste, typy blittable muszą być marshalowane.
Typy w formie tabeli blittable
W przypadku niezarządzanych interfejsów API, które używają prostych, typów wewnętrznych (zobacz Typy Blittable i Nienależące do Blittable), nie jest wymagane żadne specjalne kodowanie, ponieważ te typy danych mają taką samą reprezentację w pamięci, ale bardziej złożone typy danych wymagają jawnego marshalingu danych. Przykład można znaleźć w temacie How to: Call Native DLL from Managed Code Using PInvoke (Instrukcje: wywoływanie natywnych bibliotek DLL z kodu zarządzanego przy użyciu funkcji PInvoke).
Przykład
// 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
W tej sekcji
Instrukcje: przeprowadzanie marshalingu ciągów ANSI za pomocą międzyoperacyjności języka C++
Instrukcje: przeprowadzanie marshalingu ciągów Unicode za pomocą międzyoperacyjności języka C++
Instrukcje: przeprowadzanie marshalingu ciągów COM za pomocą międzyoperacyjności języka C++
Instrukcje: przeprowadzanie marshalingu struktur za pomocą międzyoperacyjności języka C++
Instrukcje: przeprowadzanie marshalingu tablic za pomocą międzyoperacyjności języka C++
Instrukcje: konwertowanie ciągu char * na tablicę System::Byte
Instrukcje: konwertowanie obiektu System::String na ciąg wchar_t* lub char*
Instrukcje: konwertowanie obiektu System::String na ciąg standardowy
Instrukcje: konwertowanie ciągu standardowego na obiekt System::String
Instrukcje: ładowanie zasobów niezarządzanych do tablicy typu Byte
Instrukcje: ustalanie, czy obraz jest obrazem natywnym, czy CLR
Instrukcje: dodawanie natywnej biblioteki DLL do globalnej pamięci podręcznej zestawów
Instrukcje: utrzymywanie odwołania do typu wartości w typie natywnym
Instrukcje: utrzymywanie odwołania do obiektu w pamięci niezarządzanej
Instrukcje: konwertowanie między identyfikatorami System::Guid i _GUID
Instrukcje: opakowywanie klasy natywnej do użycia w języku C#
Aby uzyskać informacje na temat używania delegatów w scenariuszu międzyoperacyjności, zobacz delegate (C++ Component Extensions).