Cómo: Calcular las referencias de cadenas COM mediante la interoperabilidad de C++
En este tema se muestra cómo se puede pasar un BSTR (el formato de cadena básico preferido en la programación COM) desde una función administrada a una función no administrada, y viceversa. Para interoperar con otros tipos de cadenas, vea los temas siguientes:
Cómo: Serializar cadenas Unicode mediante la interoperabilidad de C++
Cómo: Serializar cadenas ANSI mediante la interoperabilidad de C++
En los ejemplos de código siguientes se usan las directivas de #pragma managed, unmanaged para implementar funciones administradas y no administradas en el mismo archivo, pero estas funciones interoperan de la misma forma si se definen en archivos independientes. Los archivos que contienen solo funciones no administradas no tienen que compilarse con /clr (compilación de Common Language Runtime).
Ejemplo: Pasar BSTR de una función administrada a una no administrada
En el ejemplo siguiente se muestra cómo se puede pasar un BSTR (un formato de cadena usado en la programación COM) desde una función administrada a una no administrada. La función administrada que realiza la llamada usa StringToBSTR para obtener la dirección de una representación BSTR del contenido de un objeto System.String de .NET. Este puntero se ancla mediante pin_ptr (C++/CLI) para asegurarse de que su dirección física no cambia durante un ciclo de recolección de elementos no utilizados mientras se ejecuta la función no administrada. El recolector de elementos no utilizados tiene prohibido mover la memoria hasta que pin_ptr (C++/CLI) quede fuera 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);
}
Ejemplo: Pasar BSTR de una función no administrada a una administrada
En el ejemplo siguiente se muestra cómo se puede pasar un BSTR de una función no administrada a una administrada. La función administrada receptora puede usar la cadena como BSTR, o bien usar PtrToStringBSTR para convertirlo en un elemento String para su uso con otras funciones administradas. Dado que la memoria que representa BSTR se asigna en el montón no administrado, no es necesario el anclaje, porque no se produce recolección de elementos no utilizados en el montón no administrado.
// 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();
}