Miscellaneous Debris

Avner Kashtan's Frustrations and Exultations
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.

Published Tuesday, January 13, 2009 5:04 PM by Avner Kashtan

Filed under: , ,

Comments

# re: Tales from the Unmanaged Side – System.String –> char* (pt. 2)@ Tuesday, March 10, 2009 5:28 AM

Yes.. I absolutely agree to you. I liked the way you explained with both new and old codes...

IT consulting services

# re: Tales from the Unmanaged Side – System.String –> char* (pt. 2)@ Friday, March 27, 2009 4:59 PM

Thanks you for your clear presentation.  The MS information on this problem were not to the point.

jbaggs

# re: Tales from the Unmanaged Side – System.String –> char* (pt. 2)@ Thursday, July 23, 2009 6:26 PM

Thanks. I agree with jbaggs. Microsoft's help on this wasn't written for the ease of the reader.

Justin Bailey

Leave a Comment

(required) 
(required) 
(optional)
(required)