わんくま同盟勉強会#2で std::string ⇔ String^ および std::wstring ⇔ String^ の実装を紹介しました。
std::wstring ⇔ String^ は文字コードの変換を伴わないからいいとして、
std::string ⇔ String^ のばやい:
using namespace System::Runtime::InteropServices;
/*
* to_cli: std::string → System::String^
*/
System::String^ to_cli(const std::string& str) {
return gcnew System::String(str.c_str());
}
/*
* from_cli: System::String^ → std::string
*/
std::string from_cli(System::String^ str) {
void* ptr = Marshal::StringToHGlobalAnsi(str).ToPointer();
std::string result(static_cast<const char*>(ptr));
Marshal::FreeHGlobal(System::IntPtr(ptr));
return result;
}
…んー、どうにもキモチが悪い。
これだとSystem-loacleに応じた変換(ぶっちゃけ shift-JIS⇔Unicode)はできるけどどっこい現役でがんがってる
iso-2022-jp や EUC-jp を変換できません。
なので改版。Encodingを食わすことにしよう。
using namespace System;
using namespace System::Text;
/*
* to_cli: std::string → System::String^
*/
String^ to_cli(const std::string& input, Encoding^ encoding) {
return gcnew String(input.data(), 0, input.size(), encoding);
}
/*
* from_cli: System::String^ → std::string
*/
std::string from_cli(String^ input, Encoding^ encoding) {
array<Byte>^ result =
Encoding::Convert(Encoding::Unicode, encoding, Encoding::Unicode->GetBytes(input));
if ( result->Length != 0 ) {
pin_ptr<unsigned char> pin = &result[0];
return std::string(reinterpret_cast<char*>(pin), result->Length);
}
return std::string();
}
使い方:
Encoding^ encoding = Encoding::GetEncoding(L"shift_jis");
std::string Ninput = "漢字";
String^ Uresult = to_cli(Ninput, encoding);
String^ Uinput = L"漢字";
std::string Nresult = from_cli(Uinput, encoding);