C++ .NET convert System::String to std::string

.NetC++StringMarshalling

.Net Problem Overview


How do you convert System::String to std::string in C++ .NET?

.Net Solutions


Solution 1 - .Net

There is cleaner syntax if you're using a recent version of .net

#include "stdafx.h"
#include <string>

#include <msclr\marshal_cppstd.h>

using namespace System;

int main(array<System::String ^> ^args)
{
    System::String^ managedString = "test";

    msclr::interop::marshal_context context;
    std::string standardString = context.marshal_as<std::string>(managedString);

    return 0;
}

This also gives you better clean-up in the face of exceptions.

There is an msdn article for various other conversions

Solution 2 - .Net

And in response to the "easier way" in later versions of C++/CLI, you can do it without the marshal_context. I know this works in Visual Studio 2010; not sure about prior to that.


#include "stdafx.h"
#include <string>

#include <msclr\marshal_cppstd.h>

using namespace msclr::interop;

int main(array<System::String ^> ^args)
{
    System::String^ managedString = "test";

    std::string standardString = marshal_as<std::string>(managedString);

    return 0;
}

Solution 3 - .Net

C# uses the UTF16 format for its strings.
So, besides just converting the types, you should also be conscious about the string's actual format.

When compiling for Multi-byte Character set Visual Studio and the Win API assumes UTF8 (Actually windows encoding which is Windows-28591 ).
When compiling for Unicode Character set Visual studio and the Win API assume UTF16.

So, you must convert the string from UTF16 to UTF8 format as well, and not just convert to std::string.
This will become necessary when working with multi-character formats like some non-latin languages.

The idea is to decide that std::wstring always represents UTF16.
And std::string always represents UTF8.

This isn't enforced by the compiler, it's more of a good policy to have.

#include "stdafx.h"
#include <string>

#include <msclr\marshal_cppstd.h>
   
using namespace System;

int main(array<System::String ^> ^args)
{
    System::String^ managedString = "test";

    msclr::interop::marshal_context context;

    //Actual format is UTF16, so represent as wstring
    std::wstring utf16NativeString = context.marshal_as<std::wstring>(managedString); 

    //C++11 format converter
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    //convert to UTF8 and std::string
    std::string utf8NativeString = convert.to_bytes(utf16NativeString);

    return 0;
}

Or have it in a more compact syntax:

int main(array<System::String ^> ^args)
{
    System::String^ managedString = "test";

    msclr::interop::marshal_context context;
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    std::string utf8NativeString = convert.to_bytes(context.marshal_as<std::wstring>(managedString));

    return 0;
}

Solution 4 - .Net

stdString = toss(systemString);

  static std::string toss( System::String ^ s )
  {
    // convert .NET System::String to std::string
    const char* cstr = (const char*) (Marshal::StringToHGlobalAnsi(s)).ToPointer();
    std::string sstr = cstr;
    Marshal::FreeHGlobal(System::IntPtr((void*)cstr));
    return sstr;
  }

Solution 5 - .Net

I had too many ambiguous errors showing up with the above answers ( yes, i'm a C++ noob)

This worked for me for sending string from C# to C++ CLI

C#

bool result;
result = mps.Import(mpsToolName);

C++ CLI

function:

bool ManagedMPS::Import(System::String^ mpsToolNameTest)
std::string mpsToolName;
mpsToolName = toStandardString(mpsToolNameTest);

function that works from converting String^ to std::string

static std::string toStandardString(System::String^ string)
{
 using System::Runtime::InteropServices::Marshal;
 System::IntPtr pointer = Marshal::StringToHGlobalAnsi(string);
 char* charPointer = reinterpret_cast<char*>(pointer.ToPointer());
 std::string returnString(charPointer, string->Length);
 Marshal::FreeHGlobal(pointer);
 return returnString;
}

ON FURTHER RESEARCH, it appears that this is cleaner and safer.

I switched to using this method instead.

std::string Utils::ToUnmanagedString(String^ stringIncoming)
{
   std::string unmanagedString = marshal_as<std::string>(stringIncoming);
   return unmanagedString;
}

Solution 6 - .Net

Creating a Windows Runtime Component you can use:

String^ systemString = "Hello";
std::wstring ws1(systemString ->Data());
std::string standardString(ws1.begin(), ws1.end());

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAmish ProgrammerView Question on Stackoverflow
Solution 1 - .NetColin GravillView Answer on Stackoverflow
Solution 2 - .NetMike JohnsonView Answer on Stackoverflow
Solution 3 - .NetYochai TimmerView Answer on Stackoverflow
Solution 4 - .NetSpencer RuportView Answer on Stackoverflow
Solution 5 - .NetTom StickelView Answer on Stackoverflow
Solution 6 - .NetflaviussnView Answer on Stackoverflow