marshal_as, marshal_context

char* と System::String^の変換の方法の備忘録。Visual C++ 2008から使用可能になったmarshal_asとmarshal_contextを使うと、Marshal::StringToHGlobalAnsiなどを使うよりも若干楽ができます。

char* -> String^

#include <msclr/marshal.h>
using namespace msclr::interop;

char* ptr = "Hogehoge";

String^ str = marshal_as<String^>(ptr);

但しこの場合はStringのコンストラクタを使った方が楽かも。

char* ptr = "Hogehoge";

String^ str = gcnew String(ptr);

String^ -> char*

marshal_contextのインスタンスを作ってから、そのメソッドのmarshal_asを呼びます。

#include <msclr/marshal.h>
using namespace msclr::interop;

String^ str = "Hogehoge";

marshal_context context;
const char* ptr = context.marshal_as<const char*>(str);

constをどうしても取り除きたければ char* ptr_ = const_cast(ptr); とかやりましょう。

marshal_contextはref classなので、こう書いてもいいです。

#include <msclr/marshal.h>
using namespace msclr::interop;

String^ str = "Hogehoge";

marshal_context^ context = gcnew marshal_context();
const char* ptr = context->marshal_as<const char*>(str);

どちらにしても、スコープを抜けるとデストラクタまたはファイナライザによって解放されるので、わざわざdeleteに気を遣わなくても構いません。


複数のString^を変換する場合でも、marshal_contextは一つだけ作れば良いです。また、wchat_tなどにも変換可能です。

#include <msclr/marshal.h>
#include <msclr/marshal_windows.h>
#include <msclr/marshal_cppstd.h>
#include <msclr/marshal_atl.h>
using namespace msclr::interop;

String^ hoge = "hogehoge";
String^ fuga = "fugafuga";
String^ piyo = "piyopiyo";

marshal_context context;
const char* hogep = context.marshal_as<const char*>(hoge);
const wchar_t* fugap = context.marshal_as<const wchar_t*>(fuga);
LPCTSTR piyop        = context.marshal_as<LPCTSTR>(piyo);


さらには文字列に限らず、自分で作ったマネージクラスとネイティブの構造体の変換とかもできます。奥が深そうです。