Como realizar marshaling de cadeias de caracteres COM usando interop C++
Este tópico demonstra como um BSTR (o formato de cadeia de caracteres básico preferencial na programação do COM) pode ser passado de uma função gerenciada para uma função não gerenciada e vice-versa. Para interoperar com outros tipos de cadeias de caracteres, confira os seguintes tópicos:
Como realizar marshaling de cadeias de caracteres Unicode usando interop do C++
Como realizar marshaling de cadeias de caracteres ANSI usando interop do C++
Os exemplos de código a seguir usam as diretivas de #pragma managed, unmanaged para implementar funções gerenciadas e não gerenciadas no mesmo arquivo, mas essas funções interoperam da mesma maneira se definidas em arquivos separados. Os arquivos que contêm apenas funções não gerenciadas não precisam ser compilados com /clr (compilação do Common Language Runtime).
Exemplo: passar o BSTR da função gerenciada para não gerenciada
O exemplo a seguir demonstra como um BSTR (um formato de cadeia de caracteres usado na programação do COM) pode ser passado de uma função gerenciada para uma função não gerenciada. A função gerenciada de chamada usa StringToBSTR para obter o endereço de uma representação BSTR do conteúdo de um System.String do .NET. Esse ponteiro é fixado usando pin_ptr (C++/CLI) para garantir que seu endereço físico não seja alterado durante um ciclo de coleta de lixo enquanto a função não gerenciada é executada. O coletor de lixo fica proibido de mover a memória até que o pin_ptr (C++/CLI) saia do escopo.
// 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);
}
Exemplo: passar o BSTR de função não gerenciada para a função gerenciada
O exemplo a seguir demonstra como um BSTR pode ser passado de uma função não gerenciada para uma função gerenciada. A função gerenciada receptora pode usar a cadeia de caracteres como um BSTR ou usar PtrToStringBSTR para convertê-la em um String para uso com outras funções gerenciadas. Como a memória que representa o BSTR é alocada no heap não gerenciado, nenhuma fixação é necessária, pois não há coleta de lixo no heap não gerenciado.
// 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();
}