none
Best way from native char * to managed string RRS feed

  • Question

  • In a C++/CLI dll, I need to convert an ANSI string provided by some native code to a managed string. Currently I see two ways to do it, either by using a string ctor or by using the Marshall::PtrToStringAnsi.

    Namely, should I use 

    String ^ myManagedString = gcnew String(reinterpret_cast<const char*>(myChar));

    or 

    String ^ myManagedString = Marshal::PtrToStringAnsi((IntPtr) mychar);

     

    Any advice to make the right choice, especially with regard to performance ? Or is there a more efficient way to do it ?

     

    Thanks,

    Denis

    Monday, March 22, 2010 1:45 PM

Answers

  • Here is the result:

     

    String ^ myManagedString = gcnew String(reinterpret_cast<const char*>(myChar));

    is about twice as fast as

    String ^ myManagedString = Marshal::PtrToStringAnsi((IntPtr) mychar);
    
    (robustness of the conversion with regard to code page in another subject...)
    • Marked as answer by Denis Dollfus Wednesday, March 24, 2010 9:31 PM
    Wednesday, March 24, 2010 9:26 PM

All replies

  • The first way will not work for an ANSI string.  It is for a Unicode string.

    From MSDN [emphasis on Unicode added]:

    String Constructor (Char*)

    http://msdn.microsoft.com/en-us/library/6y4za026.aspx

    Initializes a new instance of the String class to the value indicated by a specified pointer to an array of Unicode characters.

    • Marked as answer by Denis Dollfus Tuesday, March 23, 2010 9:28 AM
    • Unmarked as answer by Denis Dollfus Wednesday, March 24, 2010 7:50 PM
    Monday, March 22, 2010 10:20 PM
  • Oh yes, thanks !

    The choice is rather simple then...

    (Edit: it seems not so simple, see below)

    Tuesday, March 23, 2010 9:33 AM
  • I jumped too quickly on you idea. Actually the String constructor used by the compiler in the first alternative is the one that takes an array of signed bytes (SByte) as parameter:

    http://msdn.microsoft.com/en-us/library/k9s9t975.aspx

    Regarding performance, I'm going to make a simple test and let you know.

    Wednesday, March 24, 2010 8:46 PM
  • Here is the result:

     

    String ^ myManagedString = gcnew String(reinterpret_cast<const char*>(myChar));

    is about twice as fast as

    String ^ myManagedString = Marshal::PtrToStringAnsi((IntPtr) mychar);
    
    (robustness of the conversion with regard to code page in another subject...)
    • Marked as answer by Denis Dollfus Wednesday, March 24, 2010 9:31 PM
    Wednesday, March 24, 2010 9:26 PM
  • Of course it's faster!  But it is also going to store total nonsense in the String object if you pass it an ANSI string.  There is a good reason PtrToStringAnsi takes longer -- the ANSI to Unicode conversion has to happen.

     

    Wednesday, March 24, 2010 11:49 PM
  • Of course it's faster!  But it is also going to store total nonsense in the String object if you pass it an ANSI string.  There is a good reason PtrToStringAnsi takes longer -- the ANSI to Unicode conversion has to happen.

     

    That isn't the case "const char *" is here the C/C++ a pointer to a signed 8bit integer (and not 16 bit of C#). The gcnew String will do the correct job. As already stated by Denis Dollfus. I used this way also for converting single byte ANSI null terminate C strings to managed Strings and never had any problems...
    Thursday, March 25, 2010 1:48 PM
  • It doesn't produce total nonsense in many cases. As I understand the documentation (http://msdn.microsoft.com/en-us/library/k9s9t975.aspx), a simple conversion takes place that convert the ANSI string to an UNICODE string using the default code page. So, ANSI string encoded with other code pages (e.g. traditional chinese or japanese as listed in http://msdn.microsoft.com/en-us/library/dd317756(VS.85).aspx) will produce, as you said, total nonsense.

    Also check the C++ example given in the same documentation page:

     

     

    // Null terminated ASCII characters in a simple char array
    char charArray3[4] = {0x41,0x42,0x43,0x00};
    char * pstr3 =  &charArray3[ 0 ];
    String^ szAsciiUpper = gcnew String( pstr3 ); 

     

     

    It produces a well-formed .Net string that contains "ABC". 

     

    Thursday, March 25, 2010 2:15 PM
  • I jumped too quickly on you idea. Actually the String constructor used by the aac compiler in the first alternative is the one that takes an array of signed bytes (SByte) as parameter:

    http://msdn.microsoft.com/en-us/library/k9s9t975.aspx

    Regarding performance, I'm going to make a simple test and let you know.


    Thanks. The documentation is exactly what I need.
    Saturday, July 24, 2010 3:38 AM