How to: Access Characters in a System::String
The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.
The latest version of this topic can be found at How to: Access Characters in a System::String.
You can access characters of a String object for high-performance calls to unmanaged functions that take wchar_t*
strings. The method yields an interior pointer to the first character of the String object. This pointer can be manipulated directly or pinned and passed to a function expecting an ordinary wchar_t
string.
Example
PtrToStringChars
returns a Char, which is an interior pointer (also known as a byref
). As such, it is subject to garbage collection. You don't have to pin this pointer unless you're going to pass it to a native function.
Consider the following code. Pinning is not needed because ppchar
is an interior pointer, and if the garbage collector moves the string it points to, it will also update ppchar
. Without a pin_ptr (C++/CLI), the code will work and not have the potential performance hit caused by pinning.
If you pass ppchar
to a native function, then it must be a pinning pointer; the garbage collector will not be able to update any pointers on the unmanaged stack frame.
// PtrToStringChars.cpp
// compile with: /clr
#include<vcclr.h>
using namespace System;
int main() {
String ^ mystring = "abcdefg";
interior_ptr<const Char> ppchar = PtrToStringChars( mystring );
for ( ; *ppchar != L'\0'; ++ppchar )
Console::Write(*ppchar);
}
abcdefg
Example
This example shows where pinning is needed.
// PtrToStringChars_2.cpp
// compile with: /clr
#include <string.h>
#include <vcclr.h>
// using namespace System;
size_t getlen(System::String ^ s) {
// Since this is an outside string, we want to be secure.
// To be secure, we need a maximum size.
size_t maxsize = 256;
// make sure it doesn't move during the unmanaged call
pin_ptr<const wchar_t> pinchars = PtrToStringChars(s);
return wcsnlen(pinchars, maxsize);
};
int main() {
System::Console::WriteLine(getlen("testing"));
}
7
Example
An interior pointer has all the properties of a native C++ pointer. For example, you can use it to walk a linked data structure and do insertions and deletions using only one pointer:
// PtrToStringChars_3.cpp
// compile with: /clr /LD
using namespace System;
ref struct ListNode {
Int32 elem;
ListNode ^ Next;
};
void deleteNode( ListNode ^ list, Int32 e ) {
interior_ptr<ListNode ^> ptrToNext = &list;
while (*ptrToNext != nullptr) {
if ( (*ptrToNext) -> elem == e )
*ptrToNext = (*ptrToNext) -> Next; // delete node
else
ptrToNext = &(*ptrToNext) -> Next; // move to next node
}
}