C++:本机到托管字符串转换问题(也许是字符集)?
C++: Native to Managed String Conversion Problem (Maybe Character Set)?
我在 return 以正确的字符集输入本机字符串时遇到问题。我从一个字符串转换为一个 wstring 到一个 LPCWSTR 以传递回托管。对于宽字符串的字符串,s2ws method 生成一个非常小的字符串 return,因为它似乎停止在我的第一个可能的终止符(在托管中),即“;”。所以,在你提到 s2ws 之前,我已经尝试了一天都没有用。
字符串内容:
char target[1024];
sprintf_s(target, 1024, "%s %s%s%s",
mac,
" (",
pWLanBssList->wlanBssEntries[t].dot11Ssid.ucSSID,
");");
std::string targetString = std::string(target);
targetWString.append(targetString.begin(), targetString.end());
后面的字符串内容:
std::wstring returnWString = L"";
returnWString.append(SomeMthod().c_str());
//wprintf_s(returnWString.c_str()); // Works - Data is in the string.
LPCWSTR returnLpcuwstr = returnWString.c_str();
return returnLpcuwstr;
我怎么知道这是字符 set/encoding 问题?好吧,当 LPCWSTR return 被管理并且我使用 Marshal 到 Unicode 字符串时,我得到了一堵 null/empty 字符。当我在 ANSI 中尝试它时,这就是我得到的(为了便于阅读而在 size/scale 中减少):
ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ
s2ws 方法应该解决 ANSI/UNICODE 噩梦,即 std::string->std::wstring 但这使得 return 太短了 - 比它应该的短得多是 - 但没有解决实际的字符集问题。
结果(对 ANSI,再次 - 我没有减少):
设想函函
当我签入 native 时,wprintf_s 显示在导出方法中发生 LPCWSTR 转换之前字符串是 valid/good;所以,我需要明白:
- 有没有办法告诉我字符的实际字节大小是多少? (我在想这是 8 字节还是 16 字节的情况?)
- 由于 wprintf_s 适用于宽字符串,我根据 LPCWSTR 检查了它,它打印了相同的(预期的)数据;因此,问题似乎不在 LPCWSTR 的 .ctor() 中。然而,我想仔细检查一下我的数学:我的 LPCWSTR 是否正确?
- 既然本机中的所有内容都告诉我字符串是好的,我如何检查它的字符集(本机中)?
return 本身大约有 8 行文本,带有分隔符“;”使用这样我就可以在托管中拆分字符串并用它来做魔术。唯一的问题是让字符串呈现为托管中的有效字符串,其中包含正确的字符。
我觉得,也许,我在这里遗漏了一些明显的东西,但我无法弄清楚它是什么,只需要一双新的眼睛来告诉我我在生活中在哪里以及如何失败。
LPCWSTR returnLpcuwstr = returnWString.c_str();
return returnLpcuwstr;
这是 return 指向数据的指针,当 returnWString
超出范围时,该指针会在 return
之后立即释放。 returned 指针 无效 在接收方甚至可以使用它之前。这是未定义的行为。
要执行您正在尝试的操作,您必须 return 一个指向动态分配内存的指针,然后接收方在使用完该内存后必须释放该内存。
假设 "managed" 您指的是 .NET,然后 .NET 的编组器使用 CoTaskMemFree()
释放非托管内存,因此如果您使用默认编组,returned 指针必须指向使用 CoTaskMemAlloc()
或等价物(例如 SysAllocString...()
)分配的内存。
否则,如果您没有使用默认封送处理(即,您正在手动调用 Marshal.PtrToStringUni()
),那么您将不得不让 .NET 代码将内存指针传递回您的 C++ 代码,以便它然后可以正确释放内存。然后您的 C++ 代码可以根据需要分配内存(只要它仍然是动态分配的,这样它就可以在函数 return 之后继续存在)。
我在 return 以正确的字符集输入本机字符串时遇到问题。我从一个字符串转换为一个 wstring 到一个 LPCWSTR 以传递回托管。对于宽字符串的字符串,s2ws method 生成一个非常小的字符串 return,因为它似乎停止在我的第一个可能的终止符(在托管中),即“;”。所以,在你提到 s2ws 之前,我已经尝试了一天都没有用。
字符串内容:
char target[1024];
sprintf_s(target, 1024, "%s %s%s%s",
mac,
" (",
pWLanBssList->wlanBssEntries[t].dot11Ssid.ucSSID,
");");
std::string targetString = std::string(target);
targetWString.append(targetString.begin(), targetString.end());
后面的字符串内容:
std::wstring returnWString = L"";
returnWString.append(SomeMthod().c_str());
//wprintf_s(returnWString.c_str()); // Works - Data is in the string.
LPCWSTR returnLpcuwstr = returnWString.c_str();
return returnLpcuwstr;
我怎么知道这是字符 set/encoding 问题?好吧,当 LPCWSTR return 被管理并且我使用 Marshal 到 Unicode 字符串时,我得到了一堵 null/empty 字符。当我在 ANSI 中尝试它时,这就是我得到的(为了便于阅读而在 size/scale 中减少):
ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ
s2ws 方法应该解决 ANSI/UNICODE 噩梦,即 std::string->std::wstring 但这使得 return 太短了 - 比它应该的短得多是 - 但没有解决实际的字符集问题。
结果(对 ANSI,再次 - 我没有减少): 设想函函
当我签入 native 时,wprintf_s 显示在导出方法中发生 LPCWSTR 转换之前字符串是 valid/good;所以,我需要明白:
- 有没有办法告诉我字符的实际字节大小是多少? (我在想这是 8 字节还是 16 字节的情况?)
- 由于 wprintf_s 适用于宽字符串,我根据 LPCWSTR 检查了它,它打印了相同的(预期的)数据;因此,问题似乎不在 LPCWSTR 的 .ctor() 中。然而,我想仔细检查一下我的数学:我的 LPCWSTR 是否正确?
- 既然本机中的所有内容都告诉我字符串是好的,我如何检查它的字符集(本机中)?
return 本身大约有 8 行文本,带有分隔符“;”使用这样我就可以在托管中拆分字符串并用它来做魔术。唯一的问题是让字符串呈现为托管中的有效字符串,其中包含正确的字符。
我觉得,也许,我在这里遗漏了一些明显的东西,但我无法弄清楚它是什么,只需要一双新的眼睛来告诉我我在生活中在哪里以及如何失败。
LPCWSTR returnLpcuwstr = returnWString.c_str();
return returnLpcuwstr;
这是 return 指向数据的指针,当 returnWString
超出范围时,该指针会在 return
之后立即释放。 returned 指针 无效 在接收方甚至可以使用它之前。这是未定义的行为。
要执行您正在尝试的操作,您必须 return 一个指向动态分配内存的指针,然后接收方在使用完该内存后必须释放该内存。
假设 "managed" 您指的是 .NET,然后 .NET 的编组器使用 CoTaskMemFree()
释放非托管内存,因此如果您使用默认编组,returned 指针必须指向使用 CoTaskMemAlloc()
或等价物(例如 SysAllocString...()
)分配的内存。
否则,如果您没有使用默认封送处理(即,您正在手动调用 Marshal.PtrToStringUni()
),那么您将不得不让 .NET 代码将内存指针传递回您的 C++ 代码,以便它然后可以正确释放内存。然后您的 C++ 代码可以根据需要分配内存(只要它仍然是动态分配的,这样它就可以在函数 return 之后继续存在)。