将System :: String转换为UTF8中的std :: string,稍后将其转换为char *作为c_str

时间:2014-12-17 12:53:10

标签: c++-cli

我在C ++代码中有一个System::String^变量。此变量应转换为std::string,后来通过const char*转换为c_str

// original string
System::String^ path = ...;

// convert to std::string
msclr::interop::marshal_context context;
std::string filename(context.marshal_as<std::string>(path));

// call API function that internally connects to sqlite3 using sqlite3_open as
//   sqlite3_open(filename.c_str())
// https://www.sqlite.org/c3ref/open.html - 
//  const char *filename,   /* Database filename (UTF-8) */
doCalculation(filename)

它适用于ASCII路径,但如果路径包含非拉丁字符则会失败。

所以不知怎的,我需要将marshalled std :: string从当前实现(ASCII?)转换为UTF8。

我试过

    std::wstring dbPath(context.marshal_as<std::wstring>(path));
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
    std::string dbPathU8 = convert.to_bytes(dbPath);

但它不起作用。

1 个答案:

答案 0 :(得分:5)

您要做的是使用.Net方法直接转换为UTF-8。

Encoding类中的可用方法并不是您正在寻找的(从托管String直接到非托管字符串或字节数组),因此我们需要一个中介和一些手动复制

String^ path = ...;

// First, convert to a managed array of the bytes you want.
array<Byte>^ bytes = Encoding::UTF8->GetBytes(path);

// Then, copy those bytes from the managed byte array to an unmanaged string.
std::string str;
str.resize(bytes->Length);
Marshal::Copy(bytes, 0, IntPtr(str.data()), bytes->Length);

// OR, copy directly to the char* you want eventually.
char* chars = new char[bytes->Length + 1]; // or malloc(), or whatever.
Marshal::Copy(bytes, 0, IntPtr(chars), bytes->Length);
chars[bytes->Length] = '\0'; // null terminate.
// don't forget to free the buffer when you're done with it!

有几种GetBytes变体可用,但它们的参数似乎既可以管理,也可以不受管理。 (String^array^,或char*byte*,但不是String ^和byte *。)因此,我们让Encoding类创建一个托管字节数组,然后我们使用Marshal::Copy方法将这些字节复制到非托管字符串对象,或直接复制到char *。