方法: C++ Interop を使用して COM 文字列をマーシャリングする
このトピックでは、BSTR (COM プログラミングで好まれる基本的な文字列形式) をマネージド関数からアンマネージド関数に渡す方法、およびその逆の方法について説明します。 他の文字列型との相互運用については、次のトピックを参照してください。
managed、unmanaged #pragma ディレクティブを使用して、同じファイルにマネージド関数とアンマネージド関数を実装する方法を次のコード例に示します。これらの関数は、別々のファイルで定義されている場合でも同じ方法で相互運用されます。 アンマネージド関数のみを含むファイルを、/clr (共通言語ランタイムのコンパイル) を使用してコンパイルする必要はありません。
例: マネージド関数からアンマネージド関数に BSTR を渡す
次の例では、BSTR (COM プログラミングで使用される文字列形式) をマネージド関数からアンマネージド関数に渡す方法を示します。 呼び出し元のマネージド関数は、StringToBSTR を使用して、.NET System.String のコンテンツの BSTR 表現のアドレスを取得します。 このポインターは 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 を渡す方法を示しています。 受信マネージド関数は、文字列 in を 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();
}