方法: C++ Interop を使用して ANSI 文字列をマーシャリングする
このトピックでは、C++ Interop を使って ANSI 文字列を渡す方法について説明しますが、.NET Framework の String は文字列を Unicode 形式で表すため、ANSI への変換は追加手順となります。 他の文字列型との相互運用については、次のトピックを参照してください。
managed、unmanaged #pragma ディレクティブを使用して、同じファイルにマネージド関数とアンマネージド関数を実装する方法を次のコード例に示します。これらの関数は、別々のファイルで定義されている場合でも同じ方法で相互運用されます。 アンマネージド関数のみを含むファイルは /clr (共通言語ランタイムのコンパイル) でコンパイルする必要がないため、パフォーマンス特性を維持することができます。
例: ANSI 文字列を渡す
この例では、StringToHGlobalAnsi を使って、マネージド関数からアンマネージド関数に ANSI 文字列を渡す例を示しています。 このメソッドは、アンマネージド ヒープ上にメモリを割り当て、変換を行った後のアドレスが返されます。 これは、(GC ヒープ上のメモリはアンマネージド関数に渡されないため) ピン留めの必要がなく、StringToHGlobalAnsi から返された IntPtr は明示的にリリースする必要があり、そうしないとメモリ リークが発生することを意味します。
// MarshalANSI1.cpp
// compile with: /clr
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma unmanaged
void NativeTakesAString(const char* p) {
printf_s("(native) received '%s'\n", p);
}
#pragma managed
int main() {
String^ s = gcnew String("sample string");
IntPtr ip = Marshal::StringToHGlobalAnsi(s);
const char* str = static_cast<const char*>(ip.ToPointer());
Console::WriteLine("(managed) passing string...");
NativeTakesAString( str );
Marshal::FreeHGlobal( ip );
}
例: ANSI 文字列のアクセスに必要なデータ マーシャリング
次の例は、アンマネージド関数から呼び出されるマネージド関数で ANSI 文字列にアクセスするために必要なデータ マーシャリングを示しています。 マネージド関数はネイティブ文字列を受け取ると、それを直接使うか、以下に示すように PtrToStringAnsi メソッドを使ってマネージド文字列に変換することができます。
// MarshalANSI2.cpp
// compile with: /clr
#include <iostream>
#include <vcclr.h>
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma managed
void ManagedStringFunc(char* s) {
String^ ms = Marshal::PtrToStringAnsi(static_cast<IntPtr>(s));
Console::WriteLine("(managed): received '{0}'", ms);
}
#pragma unmanaged
void NativeProvidesAString() {
cout << "(native) calling managed func...\n";
ManagedStringFunc("test string");
}
#pragma managed
int main() {
NativeProvidesAString();
}