managed string -> unmanaged string

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I use the following code to convert a managed string to an unmanaged one:

_TCHAR error[255];
const char* umstring = (const char*)Marshal::StringToHGlobalAnsi
(merror).ToPointer();
_tcscpy(error, umstring);
Marshal::FreeHGlobal(IntPtr((void*)umstring));

I can't use StringToHGlobalAuto because it only ever returns the first
character.
I asked why a bit ago, and somebody said you can't use StringToHGlobalAuto
because of something I can't remember, but in any case it doesn't work so
don't say that.
But they also said I need to put my own unicode checking around that, but I
can't see what the point would be - as aren't all managed strings unicode
anyway?
This leads me to believe it must be doing whatever conversions for me I
require anyway.
Is it?
If not, what is the required unicode checking?
 
=?Utf-8?B?Qm9uag==?= said:
I use the following code to convert a managed string to an unmanaged
one:

In general: For string conversion see:
HOW TO: Convert from System::String* to Char* in Visual C++ .NET
http://support.microsoft.com/kb/311259/

_TCHAR error[255];
const char* umstring = (const char*)Marshal::StringToHGlobalAnsi
(merror).ToPointer();
_tcscpy(error, umstring);
Marshal::FreeHGlobal(IntPtr((void*)umstring));

This works *only* if you have an ANSI/MBCS project!
If your projects is compiled with _UNICODE/UNICODE then it will not work!

To support TCHAR you have to do:

<code>
//#include <vcclr.h>

System::String * merror = S"Hello world";
_TCHAR error[255];
#ifdef _UNICODE
const __wchar_t __pin * umstring = PtrToStringChars(merror);
#else
const char* umstring = (const char*)Marshal::StringToHGlobalAnsi
(error).ToPointer();
#endif
_tcscpy(error, umstring);
#ifndef _UNICODE
Marshal::FreeHGlobal(IntPtr((void*)umstring));
#endif
</code>

You should also check the string length!!!!

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
Thanks very much for the example, it looks rockin'.
Just one question. What does "__pin" do?


Jochen Kalmbach said:
=?Utf-8?B?Qm9uag==?= said:
I use the following code to convert a managed string to an unmanaged
one:

In general: For string conversion see:
HOW TO: Convert from System::String* to Char* in Visual C++ .NET
http://support.microsoft.com/kb/311259/

_TCHAR error[255];
const char* umstring = (const char*)Marshal::StringToHGlobalAnsi
(merror).ToPointer();
_tcscpy(error, umstring);
Marshal::FreeHGlobal(IntPtr((void*)umstring));

This works *only* if you have an ANSI/MBCS project!
If your projects is compiled with _UNICODE/UNICODE then it will not work!

To support TCHAR you have to do:

<code>
//#include <vcclr.h>

System::String * merror = S"Hello world";
_TCHAR error[255];
#ifdef _UNICODE
const __wchar_t __pin * umstring = PtrToStringChars(merror);
#else
const char* umstring = (const char*)Marshal::StringToHGlobalAnsi
(error).ToPointer();
#endif
_tcscpy(error, umstring);
#ifndef _UNICODE
Marshal::FreeHGlobal(IntPtr((void*)umstring));
#endif
</code>

You should also check the string length!!!!

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
Jochen,
It prevents the pointer from GC.

Actually, it prevents the GC from _moving_ the object pointed to by the
__pin pointer, which is slighly different.
 
Bonj,
but it won't delete it using one of its own threads though either, no?

That's a different thing altogether... it's not the presence of the pinning
pointer that prevents garbage collection, per se, but the fact that the
object is reachable through some reference to it. In this case, the pointer
you created the pinning pointer from should suffice.

In other words, we're talking two different things here: you don't usually
pin a pointer to prevent it from getting GC'd, you pin it to prevent it from
being *moved*.

Quite different, really.
 
Right, so it doesn't matter what happens to the pointer, as long as the data
it points to is still there, but if the data gets moved, doom...
And that's what the garbage collector does isn't it.
But when the GC 'moves' a managed object legitimately, does it update the
pointer to point to the new location? Presumably this is transparent
normally in .NET but it can't happen with unmanaged pointers?

Cheers
 
Bonj,
Right, so it doesn't matter what happens to the pointer, as long as the data
it points to is still there, but if the data gets moved, doom...
And that's what the garbage collector does isn't it.

It does both... move them, and remove them
But when the GC 'moves' a managed object legitimately, does it update the
pointer to point to the new location?

Only managed handles in places that are under the GC control (i.e the
managed heap, or the managed stack). It won't update pointers in places it
it can't control (like in the CRT heap, etc.)
That's the reason to have pinning pointers: ensuring the gc doesn't move the
object referenced in memory, so that the pointers you pass to it to
unmanaged code remain valid...
 
Bonj said:
Right, so it doesn't matter what happens to the pointer, as long as the data
it points to is still there, but if the data gets moved, doom...
And that's what the garbage collector does isn't it.
Yes, after having deleted unreferneced objects, the GC compacts the
heap by moving all the remaining objects in contiguous space.
But when the GC 'moves' a managed object legitimately, does it update the
pointer to point to the new location?
It doesn't update pointers, it updates managed references (or
handles). In managed C++, those handles are represented by "managed
pointers".
Presumably this is transparent
normally in .NET but it can't happen with unmanaged pointers?
Yes, that's the whole point of pinning pointers : temporaly prevent
the GC to move an object, so that unmanaged code can use the memory
without risk of access violation.

Arnaud
MVP - VC
 
Back
Top