Condividi tramite


Utilizzo delle funzionalità di interoperabilità C++ (PInvoke implicito)

A differenza di altri linguaggi .NET, Visual C++ supporta l'interoperabilità che consente l'esistenza di codice gestito e non gestito nella stessa applicazione e anche nello stesso file (con pragmas gestito e non gestito ). In questo modo gli sviluppatori di Visual C++ possono integrare le funzionalità .NET nelle applicazioni Visual C++ esistenti senza disturbare il resto dell'applicazione.

È anche possibile chiamare funzioni non gestite da un compiland gestito usando dllexport, dllimport.

PInvoke implicito è utile quando non è necessario specificare la modalità di marshalling dei parametri della funzione o qualsiasi altro dettaglio che può essere specificato quando si chiama in modo esplicito DllImportAttribute.

Visual C++ offre due modi per l'interoperabilità tra le funzioni gestite e non gestite:

PInvoke esplicito è supportato da .NET Framework ed è disponibile nella maggior parte dei linguaggi .NET. Tuttavia, come suggerisce il nome, l'interoperabilità C++ è specifica di Visual C++.

interoperabilità C++

L'interoperabilità C++ offre una migliore sicurezza dei tipi ed è in genere meno noiosa da implementare. Tuttavia, l'interoperabilità C++ non è un'opzione se il codice sorgente non gestito non è disponibile o per i progetti multipiattaforma.

interoperabilità COM C++

Le funzionalità di interoperabilità supportate da Visual C++ offrono un particolare vantaggio rispetto ad altri linguaggi .NET quando si tratta di interagire con i componenti COM. Invece di essere limitato alle restrizioni di .NET Framework Tlbimp.exe (utilità di importazione della libreria dei tipi), ad esempio il supporto limitato per i tipi di dati e l'esposizione obbligatoria di ogni membro di ogni interfaccia COM, l'interoperabilità C++ consente l'accesso ai componenti COM e non richiede assembly di interoperabilità separati. A differenza di Visual Basic e C#, Visual C++ può usare direttamente oggetti COM usando i normali meccanismi COM, ad esempio CoCreateInstance e QueryInterface. Ciò è possibile a causa delle funzionalità di interoperabilità C++ che causano l'inserimento automatico del codice di transizione da funzioni gestite a funzioni non gestite e di nuovo.

Usando l'interoperabilità C++, i componenti COM possono essere usati normalmente oppure possono essere inclusi nelle classi C++. Queste classi wrapper sono denominate wrapper chiamabili in fase di esecuzione personalizzata o CRCWs e presentano due vantaggi rispetto all'uso diretto di COM nel codice dell'applicazione:

  • La classe risultante può essere usata da linguaggi diversi da Visual C++.

  • I dettagli dell'interfaccia COM possono essere nascosti dal codice client gestito. I tipi di dati .NET possono essere usati al posto di tipi nativi e i dettagli del marshalling dei dati possono essere eseguiti in modo trasparente all'interno di CRCW.

Indipendentemente dal fatto che COM venga usato direttamente o tramite un CRCW, è necessario effettuare il marshalling dei tipi di argomento diversi da semplici tipi copiabili.

Tipi Blittable

Per le API non gestite che usano tipi intrinseci semplici (vedere Tipi Blittable e Non Blittable), non è necessaria alcuna codifica speciale perché questi tipi di dati hanno la stessa rappresentazione in memoria, ma i tipi di dati più complessi richiedono il marshalling esplicito dei dati. Per un esempio, vedere Procedura: Chiamare DLL native da codice gestito tramite PInvoke.

Esempio

// 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

In questa sezione

Per informazioni sull'uso dei delegati in uno scenario di interoperabilità, vedere delegato (estensioni del componente C++).

Vedi anche