Procedura: effettuare il marshalling di stringhe COM utilizzando l'interoperabilità C++

In questo argomento viene illustrato come un oggetto BSTR (il formato stringa di base preferito nella programmazione COM) possa essere passato da una funzione gestita a una funzione non gestita e viceversa. Per l'interoperabilità con altri tipi di stringhe, vedere gli argomenti seguenti:

Gli esempi di codice seguenti usano le direttive #pragma gestite e non gestite per implementare funzioni gestite e non gestite nello stesso file, ma queste funzioni interagiscono nello stesso modo se definite in file separati. I file contenenti solo funzioni non gestite non devono essere compilati con /clr (compilazione Common Language Runtime).

Esempio: Passare BSTR da gestito a funzione non gestita

Nell'esempio seguente viene illustrato come un oggetto BSTR (un formato stringa usato nella programmazione COM) possa essere passato da una funzione gestita a una funzione non gestita. La funzione gestita chiamante usa StringToBSTR per ottenere l'indirizzo di una rappresentazione BSTR del contenuto di un oggetto System.String .NET. Questo puntatore viene aggiunto usando pin_ptr (C++/CLI) per assicurarsi che l'indirizzo fisico non venga modificato durante un ciclo di Garbage Collection mentre viene eseguita la funzione non gestita. Il Garbage Collector non è consentito spostare la memoria finché il pin_ptr (C++/CLI) non esce dall'ambito.

// MarshalBSTR1.cpp
// compile with: /clr
#define WINVER 0x0502
#define _AFXDLL
#include <afxwin.h>

#include <iostream>
using namespace std;

using namespace System;
using namespace System::Runtime::InteropServices;

#pragma unmanaged

void NativeTakesAString(BSTR bstr) {
   printf_s("%S", bstr);
}

#pragma managed

int main() {
   String^ s = "test string";

   IntPtr ip = Marshal::StringToBSTR(s);
   BSTR bs = static_cast<BSTR>(ip.ToPointer());
   pin_ptr<BSTR> b = &bs;

   NativeTakesAString( bs );
   Marshal::FreeBSTR(ip);
}

Esempio: Passare BSTR da una funzione non gestita a una funzione gestita

Nell'esempio seguente viene illustrato come passare un oggetto BSTR da una funzione non gestita a una funzione gestita. La funzione gestita ricevente può usare la stringa in come BSTR o usarla PtrToStringBSTR per convertirla in un String oggetto da usare con altre funzioni gestite. Poiché la memoria che rappresenta la stringa BSTR viene allocata nell'heap non gestito, non è necessaria alcuna aggiunta, perché non è presente garbage collection nell'heap non gestito.

// MarshalBSTR2.cpp
// compile with: /clr
#define WINVER 0x0502
#define _AFXDLL
#include <afxwin.h>

#include <iostream>
using namespace std;

using namespace System;
using namespace System::Runtime::InteropServices;

#pragma managed

void ManagedTakesAString(BSTR bstr) {
   String^ s = Marshal::PtrToStringBSTR(static_cast<IntPtr>(bstr));
   Console::WriteLine("(managed) convered BSTR to String: '{0}'", s);
}

#pragma unmanaged

void UnManagedFunc() {
   BSTR bs = SysAllocString(L"test string");
   printf_s("(unmanaged) passing BSTR to managed func...\n");
   ManagedTakesAString(bs);
}

#pragma managed

int main() {
   UnManagedFunc();
}

Vedi anche

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