What is the best way to convert between char* and System::String in C++/CLI

68,729

Solution 1

There's a good overview here (this marshaling support added for VS2008): http://www.codeproject.com/KB/mcpp/OrcasMarshalAs.aspx

Solution 2

System::String has a constructor that takes a char*:

 using namespace system;
 const char* charstr = "Hello, world!";
 String^ clistr = gcnew String(charstr);
 Console::WriteLine(clistr);

Getting a char* back is a bit harder, but not too bad:

 IntPtr p = Marshal::StringToHGlobalAnsi(clistr);
 char *pNewCharStr = static_cast<char*>(p.ToPointer());
 cout << pNewCharStr << endl;
 Marshal::FreeHGlobal(p);
Share:
68,729

Related videos on Youtube

Brian Stewart
Author by

Brian Stewart

Updated on July 09, 2022

Comments

  • Brian Stewart
    Brian Stewart almost 2 years

    What is the approved way to convert from char* to System::string and back in C++/CLI? I found a few references to marshal_to<> templated functions on Google, but it appears that this feature never made the cut for Visual Studio 2005 (and isn't in Visual Studio 2008 either, AFAIK). I have also seen some code on Stan Lippman's blog, but it's from 2004. I have also seen Marshal::StringToHGlobalAnsi(). Is there a method that is considered "best practice"?

  • Anthony Serdyukov
    Anthony Serdyukov about 14 years
    +1, System::String constructor also takes length and encoding!
  • Ben Voigt
    Ben Voigt over 12 years
    Marshal::StringToHGlobalAnsi is a poor option compared to marshal_context (as mentioned by Matthew), which uses RAII to automatically free the buffer. Not to mention that the name is totally wrong, it doesn't return an HGLOBAL at all.
  • Patrick.SE
    Patrick.SE about 12 years
    Probably have to Marshal::FreeHGlobal(IntPtr((void*)chars)); it
  • dko
    dko about 12 years
    @Pat yes sorry I should have updated this after this. I did get it working well now. Moving it to .NET increased the performance of this app by 3x. Even marshaling things around.
  • gatopeich
    gatopeich over 11 years
    Thanks, but that is a lengthy explanation. This goes more to the point: #include <msclr\marshal.h> // marshal_context context; // my_c_string = context.marshal_as<const char*>(my_csharp_string);
  • Mugen
    Mugen about 6 years
    For those who wonder, the full namespace for context is msclr::interop::marshal_context
  • Dewey Vozel
    Dewey Vozel over 5 years
    Your example does not work for me in C++/CLI using .NET 4.6.1. There is no System::String constructor that takes a char*... only signed char* or wchar_t*
  • Ben Straub
    Ben Straub over 5 years
    It's been a while since I've been in this world, but I believe this should still work. According to the docs at docs.microsoft.com/en-us/cpp/windows/…, you should still be able to gcnew a string with a char * string as the argument. Maybe you can cast to signed char *?
  • Menace
    Menace over 3 years
    From my experience the pointer also has no nul terminator. You need to use clistr.Length to know how long it is.