Tales from the Unmanaged Side – System.String –> char* (pt. 2)

Tags: .NET, C++CLI, CodeSnippets

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.