managed string -> unmanaged string

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?
 
J

Jochen Kalmbach

=?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/
 
G

Guest

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/
 
T

Tomas Restrepo \(MVP\)

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.
 
T

Tomas Restrepo \(MVP\)

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.
 
B

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.
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
 
T

Tomas Restrepo \(MVP\)

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...
 
A

Arnaud Debaene

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top