.NET Framework - String^, const char*, std::string, and c_str( )

Asked By Kevin Frey
20-Feb-07 04:52 PM
I am porting Managed C++ code from VS2003 to VS2005. Therefore adopting the
new C++/CLI syntax rather than /clr:oldSyntax.

Much of our managed code is concerned with interfacing to native C++ code
(ie. wrappers etc). In Managed C++ there was an automatic conversion between
const char* and String^. This was useful to us for two reasons:

1. We declared our string constants as eg. const char* const c_My_Constant =
a std::string or a String^.
2. We could easily convert/assign std::string to String^ using the .c_str( )
method.

Both of these techniques no longer work in C++/CLI. The implicit conversion
has now disappeared.

Now, in case (2) I have no problem changing all this code to instead use a
probably even has the benefit of making the code more readable.

I could obviously do the same thing for case (1) but it irks me to have to
convert a "constant". Unfortunately, however, I have numerous situations
where the same constant will be used by both native and managed C++.

Is there a better way to achieve this?

Thanks

Kevin
CLI
(1)
ISO
(1)
TCHAR
(1)
MC
(1)
C_My_Constant
(1)
KevinRe
(1)
MagicStrings
(1)
OldSyntax
(1)
  Tamas Demjen replied...
20-Feb-07 05:46 PM
You don't need a to_string() function. You can construct a String
directly from a const char*:

std::string s;
String^ managed_str = gcnew String(s.c_str());


You certainly don't have to convert a literal, you can assign it directly:

String^ ms2 = "Hello";

A const char* is not a literal constant, and requires conversion, even
in VC++ 2003 and /clr:oldSntax. const char* is using 1 byte per
character, while String^ is using 2 bytes. Also, const char* uses
unmanaged memory, while String^ is garbage collected. They're not
compatible. In the old MC++, this conversion was implicit, but it was a
conversion function nonetheless.


You can not really have the same code compile for .NET and ISO C++. The
syntax is vastly different, just think about class vs ref class / value
class, or enum vs enum class, etc. You can compile ISO C++ syntax to
managed code, but ISO C++ declarations won't be accessible from outside
of the assembly, and ISO C++ types will be unmanaged types.

The following, however, will always work with both ISO C++ and C++/CLI,
without 0 overhead:


In the old MC++, you use to have to write S"Hello", which was much
worse. You no longer have to do that, all you need is the double quotes.
So the situation in C++/CLI is not worse, but much better than it used
to be.

In the old MC++, every time you did this, you had a conversion overhead,
whether you realized that or not:

const char* my_str = "Hello";
String* managed_str = my_str;

That's exactly the same overhead as the following in C++/CLI:

const char* my_str = "Hello";
String^ managed_str = gcnew String(my_str);

Tom
  Kevin Frey replied...
20-Feb-07 06:18 PM
Hi Tom,


Sure, I knew this. But to my eyes it is ugly. It expresses the mechanics of
the conversion every time (and hence in every place) it is expressed. I
would therefore much rather have:

String^ managed_str = to_string( s );

Which hides the mechanics of the conversion. Inlining the code should result
in no performance hit either.


Yes, but in practice we don't sprinkle lots of "magic strings" around our
code like your example, hence it doesn't help us much, and most examples
found on the internet seems to focus on this type of example. If there are
constants involved they are declared as const char* const constants. We
could use preprocessor macros as you suggest but once again it seems ugly,
and more importantly, regressive to have to do so.


Yes, I did say that I understood that there was an automatic/implicit
conversion going on. And now there isn't in C++/CLI. I am not concerned with
the performance implication - after all there *used* to be a conversion
going on anyway. My interest was determining whether I could get the
conversion for free (coding-wise), rather than being explicit about it.


You have over-extrapolated the extent of my comment. I was not trying to
re-use the same code, I was trying to re-use some of the same string
constants. Nothing more, nothing less. Perhaps a filename that is used by
both managed and native code, as an example.

Thanks for your input - it seems to be confirming to me that I'm going to
have to perform some explicit conversions along the way.

Kevin
  Tamas Demjen replied...
20-Feb-07 09:03 PM
I understand your reasoning, and you are right. The implicit conversion
was quite convenient in MC++.


Sorry about that.


But you can't even reuse string constants very easily. For managed
types, the syntax is:

public ref struct MagicStrings
{
literal String^ name1 = "value1";
literal String^ name2 = "value2";
};

In native C++, it's:

// Into the .h file:
extern const TCHAR* name1;
extern const TCHAR* name2;

// Into the .cpp file:
const TCHAR* name1 = _T("value1");
const TCHAR* name2 = _T("value2");

Tom
Create New Account
help
The various levels of / CLI .NET Framework My program works great in 'vanilla' / CLI, so I tried both ' / CLI pure' and / CLI 'safe'. My program continues to compile and run fine in 'CLI pure' (I also use error level 4 and don't even get warning errors), but generates almost 400 compile time errors in ' / CLI safe'. So, more out of curiosity, what are the advantages and disadvantages to each 'level' of / CLI? Since mine will compile and run in ' / CLI pure' what am I 'getting' I wouldn't get if it only worked under 'vanilla
Cliente que me crea de forma automatica el DataContex, el codigo es el siguiente: Cliente cli = 3D new Cliente(); cli.Nombre = 3D"Nombre Completo"; cli.Direccion = 3D"Dir"; cli.Poblacion = 3D"Pobl"; cli.Provincia = 3D"Prov"; cli.CP = 3D"CP"; cli.Pais = 3D"Pais"; cli.NIF = 3D"NIF"; cli.Descr = 3D"Descr"; dc.Clientes.InsertOnSubmit(cli); Si ahora quiero recorrer
in VS2008 .NET Framework Why bother having Stan Lippman and Herb Sutter created a C++ / CLI language for .Net development when Microsoft, and the VC++ development team, are so clearly intent on limiting .Net development with C++ / CLI to the smallest subset of .Net development technologies in Visual Studio, while all of the to be a first-class .Net development language. In that case why bother with C++ / CLI, since it serves little to no purpose for C++ programmers anymore. Here is the lineup 3) WPF, not for C++ and even creating controls for WPF is absent for C++ / CLI. 4) WCF, not for C++. 5) WWF, not for C++ 6) LINQ, not for C a RAD technology like .Net so I could go back to doing MFC development. C++ / CLI is such a good language, with so much careful and intelligent decisions made so that and Python very well, thank you. So it is absolutely normal to you that C++ / CLI, despite being a version of C++ expressly created for .Net programming, should not have the obsoleted by the very same people who hyped and promised in the first place. C++ / CLI was created as a means for C++ programmers to be on equal footing when using obviously shown in the current VS 2008 release that it will not happen, that C++ / CLI will be treated as a second class .Net language, by the very same people who
How do you create an array of pointers to managed types? (C++ / CLI) .NET Framework I have an array cli::array<float, 2> and I would like to access a subset of it's values an array of pointers. But, it's not possible to create an array of type cli:array<cli::interior_ptr<float> , 2> . . . So, what do I do? VC++.NET Discussions DataColumn (1) ArrayList (1 think interior_ptr is a native type so you'd use a normal C++ array (not cli::array). You can make .NET arrays of tracking handles of course (cli::array<T^, 2> where T is a .NET reference type). Of course, you could store array instead of interior_ptr. I've tried using an array of tracking handles like this. . . cli::array<float ^, 2> ^handles; cli::array<float, 2> ^data; data = gcnew cli::array<float, 2> { {0, 0}, {10, 10}, {20