Is it possible to get a pointer to String^'s internal array in C++/CLI?
문제
The goal is to avoid copying the string data when I need a const wchar_t*
.
The answer seems to be yes, but the function PtrToStringChars
doesn't have its own MSDN entry (it's only mentioned in the KB and blogs as a trick). That made me suspicious and I want to check with you guys. Is it safe to use that function?
해결책
Yes, no problem. It is actually somewhat documented but hard to find. The MSDN docs for the C++ libraries aren't great. It returns an interior pointer, that's not suitable for conversion to a const wchar_t* yet. You have to pin the pointer so the garbage collector cannot move the string. Use pin_ptr<> to do that.
You can use Marshal::StringToHGlobalUni() to create a copy of the string. Use that instead if the wchar_t* needs to stay valid for an extended period of time. Pinning objects too long isn't very healthy for the garbage collector.
다른 팁
Here is a complete solution based on PtrToStringChars that accesses the managed string internals and then copies the contents using standard C functions:
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;
}
According to this article: http://support.microsoft.com/kb/311259 PtrToStringChars is officially supported and may be used. It is described as "get an interior gc pointer to the first character contained in a System::String object" in vcclr.h .