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

Ale*_*hov 0 c++-cli

我有一个System::String^C++代码变量.应将此变量转换std::string为稍后转换为const char*via的变量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)
Run Code Online (Sandbox Code Playgroud)

它适用于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);
Run Code Online (Sandbox Code Playgroud)

但它不起作用.

Dav*_*Yaw 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!
Run Code Online (Sandbox Code Playgroud)

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