Cómo: Calcular referencias de cadenas COM mediante la interoperabilidad de C++

Actualización: noviembre 2007

El tema siguiente muestra cómo se puede hacer que BSTR (el formato de cadena básico preferido en programación COM) pase de una función administrada a no administrada, y al contrario. Para interactuar con otros tipos de cadenas, consulte los temas siguientes:

En los siguientes ejemplos de código, se utilizan las directivas #pragma managed, unmanaged para implementar funciones administradas y no administradas en el mismo archivo, pero sin que éstas dejen de interactuar como si se hubieran definido en archivos separados. No es necesario compilar con /clr (Compilación de Common Language Runtime) los archivos que contienen únicamente funciones no administradas.

Ejemplo

El ejemplo siguiente muestra cómo se puede hacer que BSTR (un formato de cadena utilizado en programación COM) pase de una función administrada a no administrada. La función administrada de llamada utiliza StringToBSTR para obtener la dirección de una representación de BSTR del contenido de una System.String de .NET. Este puntero se fija mediante pin_ptr, para asegurarse de que su dirección física no cambie durante un ciclo de recolección de elementos no utilizados mientras se ejecuta la función no administrada. El recolector de elementos no utilizados no puede de ningún modo mover la memoria hasta que pin_ptr salga del ámbito.

// 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);
}

El ejemplo siguiente muestra cómo se puede hacer que BSTR pase de una función no administrada a una administrada. La función administrada receptora puede utilizar la cadena como BSTR, o usar PtrToStringBSTR para convertirla en String y poder utilizarla con otras funciones administradas. Dado que la memoria que representa BSTR está asignada en el montón no administrado, no es necesario fijar, ya que no hay recolección de elementos no utilizados en dicho montón.

// 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();
}

Vea también

Referencia

Utilizar la interoperabilidad de C++ (PInvoke implícito)