10

So i work in clr, creating .net dll in visual c++.

I tru such code:

 static bool InitFile(System::String^ fileName, System::String^ container)
{
    return enc.InitFile(std::string(fileName), std::string(container));
}

having encoder that normaly resives std::string. but here the compiler (visual studio) gives me C2664 error if I strip out arguments from std::string and C2440 which is in general the same. VS tells me that it just can not to convert System::String^ into std::string.

So I am sad... what shall I do to turn System::String^ into std::string?

Update:

Now with your help I have such code

#include <msclr\marshal.h>
#include <stdlib.h>
#include <string.h>
using namespace msclr::interop;
namespace NSSTW
{
  public ref class CFEW
  {
 public:
     CFEW() {}

     static System::String^ echo(System::String^ stringToReturn)
    {
        return stringToReturn;  
    }

     static bool InitFile(System::String^ fileName, System::String^ container)
    {   
        std::string sys_fileName = marshal_as<std::string>(fileName);;
        std::string sys_container = marshal_as<std::string>(container);;
        return enc.InitFile(sys_fileName, sys_container);
    }
...

but when I try to compile it gives me C4996

error C4996: 'msclr::interop::error_reporting_helper<_To_Type,_From_Type>::marshal_as': This conversion is not supported by the library or the header file needed for this conversion is not included. Please refer to the documentation on 'How to: Extend the Marshaling Library' for adding your own marshaling method.

what to do?

Rella
  • 65,003
  • 109
  • 363
  • 636

4 Answers4

8

If you're using VS2008 or newer, you can do this very simply with the automatic marshaling added to C++. For example, you can convert from System::String^ to std::string via marshal_as:

System::String^ clrString = "CLR string";
std::string stdString = marshal_as<std::string>(clrString);

This is the same marshaling used for P/Invoke calls.

Chris Schmich
  • 29,128
  • 5
  • 77
  • 94
  • I like idea but how to declare marshal_as in my code? where and what shall i write to declare it (to get rid of error C2065) , I use VS2008 – Rella Aug 21 '10 at 23:03
  • 1
    To go from `System::String^` to `std::string`, you need to `#include ` where `marshal_as` is declared. – Chris Schmich Aug 21 '10 at 23:06
  • when I try #include it gives me fatal error C1083... so I edited code and posted it here in Question (I use what they used in MS MSDN example)... can you take a look at it please. – Rella Aug 21 '10 at 23:14
  • Sorry, I was slightly off, you need to include `msclr\marshal_cppstd.h`. Are you still having this issue? Your code above still says `msclr\marshal.h`. – Chris Schmich Aug 21 '10 at 23:21
  • msclr\marshal.h is also fine. Thanks btw. :) – Jakub Matczak Jan 06 '13 at 17:01
4

From the article How to convert System::String^ to std::string or std::wstring on MSDN:

void MarshalString (String ^ s, string& os) 
{
    using namespace Runtime::InteropServices;
    const char* chars = 
      (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
    os = chars;
    Marshal::FreeHGlobal(IntPtr((void*)chars));
}

Usage:

std::string a;
System::String^ yourString = gcnew System::String("Foo");
MarshalString(yourString, a);
std::cout << a << std::endl; // Prints "Foo"
Håvard S
  • 23,244
  • 8
  • 61
  • 72
3

You need to include marshal_cppstd.h to convert String^ to std::string.

You don't mention if you're concerned at all about non-ascii characters. If you need unicode (and if not, why not!?), there is a marshal_as which returns a std::wstring.

If you're using utf8, you'll have to roll your own. You can use a simple loop:

System::String^ s = ...;
std::string utf8; 
for each( System::Char c in s )
    // append encoding of c to "utf8";
1

How to convert from System::String* to Char* in Visual C++

Once you have a char*, simply pass it to the std::string constructor.

dan04
  • 87,747
  • 23
  • 163
  • 198