【发布时间】:2011-03-04 00:48:27
【问题描述】:
目标是在我需要const wchar_t* 时避免复制字符串数据。
答案似乎是肯定的,但是函数PtrToStringChars 没有自己的MSDN 条目(它只是在知识库和博客中作为技巧提及)。这让我很怀疑,我想和你们核实一下。使用该功能是否安全?
【问题讨论】:
目标是在我需要const wchar_t* 时避免复制字符串数据。
答案似乎是肯定的,但是函数PtrToStringChars 没有自己的MSDN 条目(它只是在知识库和博客中作为技巧提及)。这让我很怀疑,我想和你们核实一下。使用该功能是否安全?
【问题讨论】:
这是一个基于 PtrToStringChars 的完整解决方案,它访问托管字符串内部,然后使用标准 C 函数复制内容:
wchar_t *ManagedStringToUnicodeString(String ^s)
{
// Declare
wchar_t *ReturnString = nullptr;
long len = s->Length;
// Check length
if(len == 0) return nullptr;
// Pin the string
pin_ptr<const wchar_t> PinnedString = PtrToStringChars(s);
// Copy to new string
ReturnString = (wchar_t *)malloc((len+1)*sizeof(wchar_t));
if(ReturnString)
{
wcsncpy(ReturnString, (wchar_t *)PinnedString, len+1);
}
// Unpin
PinnedString = nullptr;
// Return
return ReturnString;
}
【讨论】:
是的,没问题。它实际上有点documented,但很难找到。 C++ 库的 MSDN 文档不是很好。它返回一个内部指针,目前还不适合转换为 const wchar_t*。您必须固定指针,以便垃圾收集器无法移动字符串。使用 pin_ptr 来做到这一点。
您可以使用 Marshal::StringToHGlobalUni() 来创建字符串的副本。如果 wchar_t* 需要长时间保持有效,请使用它。将对象固定太久对垃圾收集器来说不是很健康。
【讨论】:
StringToHGlobalUni。使用 PtrToStringChars 然后自己制作副本可能比使用 HGLOBAL 快很多,HGLOBAL 是一种实际用途有限的专用分配器。实际上marshal_as<BSTR> 或marshal_as<std::wstring> 将被推荐为本地副本。 msdn.microsoft.com/en-us/library/bb384865.aspx