Tales from the Unmanaged Side – System.String –> char* (pt. 2)
A while ago, I posted an entry about marshalling a managed System.String into an unmanaged C string, specifically a plain char*. The solution I suggested, back in 2007, involved calling Marshal::StringToHGlobalAuto method to allocate memory and copy the string data into it, and then cast the HGlobal pointer into a char*.
It seems that in Visual Studio 2008 a new way of doing it was added, as part of the new Marshalling Library. This library provides a whole set of conversions between System.String and popular unmanaged string representations, like char*, wchar_t*, BSTR, CStringT<wchar_t> and others I am even less familiar with.
The smarter string representations, like std::string, have their own destructors so I can carelessly let them drop out of scope without worrying about leaks. The more primitive ones, like char*, need to be explicitly released, so that’s why the Marshalling Library contains a new (managed) class called marshal_context which gives me exactly this explicit release.
Let’s compare my old code with the new:
1: const char* unmanagedString = NULL;
2: try
3: {
4: String^ managedString = gcnew String("managed string");
5: // Note the double cast.
6: unmanagedString = (char*)(void*)Marshal::StringToHGlobalAnsi(managedString);
7: }
8: finally
9: {
10: // Don't forget to release. Note the ugly casts again.
11: Marshal::FreeHGlobal((IntPtr)(void*)unmanagedString);
12: }
And the new:
1: marshal_context^ context = gcnew marshal_context();
2: String^ managedString = gcnew String("managed string");
3: const char* unmanagedString = context->marshal_as<const char*>( managedString );
Much shorter, I’m sure you’ll agree. And neater – no need for all the icky, icky casting between different pointer types. And most importantly, I don’t have to explicitly release the char* – the marshal_context class keeps a reference to all the strings that were marshalled through it, and when it goes out of scope its destructor makes sure to release them all. Very efficient, all in all.
6 Comments
Comments have been disabled for this content.
IT consulting services said
Yes.. I absolutely agree to you. I liked the way you explained with both new and old codes...
jbaggs said
Thanks you for your clear presentation. The MS information on this problem were not to the point.
Justin Bailey said
Thanks. I agree with jbaggs. Microsoft's help on this wasn't written for the ease of the reader.
weblogs.asp.net said
Tales from the unmanaged side system string gt char pt 2.. Reposted it :)
weblogs.asp.net said
Tales from the unmanaged side system string gt char pt 2.. Very nice :)
serak said
what about marshal_as() method it can literally convert anything.