2
votes

I try to convert a String^ to basic string...but I get the error after this code. What does it mean and how can I fix it? I need to input basic string into a class constructor. The string^ would not work.

System::String^ temp = textBox1->Text;
string dummy = System::Convert::ToString(temp);
error C2440: 'initializing' : cannot convert from 'System::String ^' to 'std::basic_string'
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits,
1>            _Ax=std::allocator
1>        ]
1>        No constructor could take the source type, or constructor overload resolution was ambiguous
6

6 Answers

9
votes

You need to marshal your string. The managed string sits somewhere on the managed heap (garbage collector is free to move it around).

One way of getting the string to the native side is as follows:

using System::Runtime::InteropServices::Marshal;

char *pString = (char*)Marshal::StringToHGlobalAnsi(managedString);
std::string nativeString(pString); // make your std::string
Marshal::FreeHGlobal(pString);     // don't forget to clean up

If you are using Visual Studio 2008, you can take advantage of much nicer marshaling utilities. Check out this MSDN page.

#include <msclr/marshal.h>
#include <msclr/marshal_cppstd.h>

using namespace msclr::interop;

std::string nativeString(marshal_as<std::string>(managedString));
3
votes

I spend 11h to find a solution:

 #include <stdlib.h
 #include <string.h>
 #include <msclr\marshal_cppstd.h>
 //ListaQuad<int> prueba;
 //..
 using namespace msclr::interop;
 //..
 System::String^ clrString = (TextoDeBoton);
 std::string stdString = marshal_as<std::string>(clrString);  //String^ to std
 //System::String^ myString = marshal_as<System::String^>(MyBasicStirng);   //std to String^ (no lo he probado, pero sería algo así.)
 prueba.CopyInfo(stdString); //MyMethod
 //..
 //where, String^ = TextoDeBoton;
 //and, stdString = normal string;
2
votes

You need to do two things to convert a System::String to a std::string:

  • Marshal the memory from the managed heap an unmanaged one.
  • Convert your character encoding from a wide characters to (what looks like from your question) ansi characters.

One way, without having to worry about freeing any HGlobal memory is to define a method along the lines of:

interior_ptr<unsigned char> GetAsciiString(System::String ^s)
{
    array<unsigned char> ^chars = System::Text::Encoding::ASCII->GetBytes(s);
    return &chars[0];
    // of course you'd want to do some error checking for string length, nulls, etc..
}

And you'd use it like:

// somewhere else...
{
    pin_ptr<unsigned char> pChars = GetAsciiString(textBox1->Text);
    std:string std_str(pChars); // I don't have my compiler in front of me, so you may need a (char*)pChars
}

This also lets you use the encoding of your choice (like utf-8 over ascii), but you may not really need this.

1
votes

May be, you will need inverse converting, from std::string to String^. I was searching this converting, but I didn't find. So, I wrote it. I hope, it will be useful for somebody:

String^ stdStringToPlatformString(string stdString){
    const size_t newsizew = strlen(stdString.c_str()) + 1;
    size_t convertedChars = 0;
    wchar_t *ch1 = new wchar_t[newsizew];
    mbstowcs_s(&convertedChars, ch1, newsizew, stdString.c_str(), _TRUNCATE);
    String ^platformString;
    platformString = ref new Platform::String(ch1, newsizew);
    return platformString;
}    
0
votes

I think you can also just do:

string dummy = string( textBox1->Text );

Check out How to: Convert Between Various String Types on MSDN.

0
votes
string platformStringToStdString(String ^input){
    int size=input->Length()+1;
    char* auxiliary=(char *)malloc(sizeof(char)*size);
    wcstombs_s(NULL,auxiliary,size,input->Data(),_TRUNCATE);
    string result(auxiliary);
    free(auxiliary);
    return result;
}