Практическое руководство. Маршалирование строк COM с помощью взаимодействия C++
В этом разделе показано, как BSTR (базовый формат строки, предпочитаемый в программировании COM), может передаваться из управляемой функции в неуправляемую функцию и наоборот. Сведения о взаимодействии с другими типами строк см. в следующих разделах:
Практическое руководство. Маршалинг строк Юникода с использованием взаимодействия C++
Практическое руководство. Маршалинг строк ANSI с использованием взаимодействия C++
В следующих примерах кода используются управляемые неуправляемые директивы #pragma для реализации управляемых и неуправляемых функций в одном файле, но эти функции взаимодействуют одинаково, если они определены в отдельных файлах. Файлы, содержащие только неуправляемые функции, не нужно компилировать с помощью /clr (компиляция clr (компиляция среды clr).
Пример. Передача BSTR из управляемой в неуправляемую функцию
В следующем примере показано, как BSTR (строковый формат, используемый в программировании COM) можно передать из управляемой неуправляемой функции. Вызывающая управляемая функция используется StringToBSTR для получения адреса представления BSTR содержимого .NET System.String. Этот указатель закреплен с помощью pin_ptr (C++/CLI), чтобы убедиться, что его физический адрес не изменяется во время цикла сборки мусора во время выполнения неуправляемой функции. Сборщик мусора запрещается перемещать память до тех пор, пока pin_ptr (C++/CLI) не выходит из области.
// 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);
}
Пример. Передача BSTR из неуправляемой функции в управляемую функцию
В следующем примере показано, как BSTR можно передать из неуправляемой функции в управляемую функцию. Получающая управляемая функция может использовать строку в качестве BSTR или PtrToStringBSTR использовать для преобразования ее в String функцию для использования с другими управляемыми функциями. Так как память, представляющая BSTR, выделяется на неуправляемой куче, не требуется закрепление, так как на неуправляемой куче нет сборки мусора.
// 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();
}