我在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);
但它不起作用。
答案 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 *。