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